From a189b2ee938f6b15ad9f95bdef63f95a3a092418 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 17 Nov 2022 12:47:29 +0100 Subject: fbdev: Make fb_modesetting_disabled() static inline Make fb_modesetting_disabled() a static-inline function when it is defined in the header file. Avoid the linker error shown below. ld: drivers/video/fbdev/core/fbmon.o: in function `fb_modesetting_disabled': fbmon.c:(.text+0x1e4): multiple definition of `fb_modesetting_disabled'; drivers/video/fbdev/core/fbmem.o:fbmem.c:(.text+0x1bac): first defined here A bug report is at [1]. Reported-by: Stephen Rothwell Reported-by: kernel test robot Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Fixes: 0ba2fa8cbd29 ("fbdev: Add support for the nomodeset kernel parameter") Cc: Javier Martinez Canillas Cc: Daniel Vetter Cc: Helge Deller Cc: linux-fbdev@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Link: https://lore.kernel.org/dri-devel/20221117183214.2473e745@canb.auug.org.au/T/#u # 1 Link: https://patchwork.freedesktop.org/patch/msgid/20221117114729.7570-1-tzimmermann@suse.de --- include/linux/fb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/fb.h b/include/linux/fb.h index 8dc9635f5bc1..a2a52f730989 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -807,7 +807,7 @@ extern int fb_find_mode(struct fb_var_screeninfo *var, #if defined(CONFIG_VIDEO_NOMODESET) bool fb_modesetting_disabled(const char *drvname); #else -bool fb_modesetting_disabled(const char *drvname) +static inline bool fb_modesetting_disabled(const char *drvname) { return false; } -- cgit v1.2.3 From 7aa3d63e1ad56c174536a5aba76d8a54c4c5acb4 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 18 Nov 2022 14:35:33 +0100 Subject: Revert "drm/fb-helper: Remove damage worker" This reverts commit 27c3e9452d552ea86369a94f23287a9675f2d7a1. Needed to restore the fbdev damage worker. There have been bug reports about locking order [1] and incorrectly takens branches. [2] Restore the damage worker until these problems have been resovled. Signed-off-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://intel-gfx-ci.01.org/tree/drm-tip/fi-kbl-8809g.html # 1 Link: https://lore.kernel.org/dri-devel/20221115115819.23088-6-tzimmermann@suse.de/T/#m06eedc0a468940e4cbbd14ca026733b639bc445a # 2 Link: https://patchwork.freedesktop.org/patch/msgid/20221118133535.9739-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_fb_helper.c | 9 +++++++++ include/drm/drm_fb_helper.h | 2 ++ 2 files changed, 11 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index a1f86e436ae8..c0e9a977a3b3 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -403,6 +403,13 @@ err: spin_unlock_irqrestore(&helper->damage_lock, flags); } +static void drm_fb_helper_damage_work(struct work_struct *work) +{ + struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, damage_work); + + drm_fb_helper_fb_dirty(helper); +} + /** * drm_fb_helper_prepare - setup a drm_fb_helper structure * @dev: DRM device @@ -418,6 +425,7 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, INIT_LIST_HEAD(&helper->kernel_fb_list); spin_lock_init(&helper->damage_lock); INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker); + INIT_WORK(&helper->damage_work, drm_fb_helper_damage_work); helper->damage_clip.x1 = helper->damage_clip.y1 = ~0; mutex_init(&helper->lock); helper->funcs = funcs; @@ -549,6 +557,7 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) return; cancel_work_sync(&fb_helper->resume_work); + cancel_work_sync(&fb_helper->damage_work); info = fb_helper->info; if (info) { diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h index 455f6c2b8117..b111dc7ada78 100644 --- a/include/drm/drm_fb_helper.h +++ b/include/drm/drm_fb_helper.h @@ -116,6 +116,7 @@ struct drm_fb_helper_funcs { * @damage_clip: clip rectangle used with deferred_io to accumulate damage to * the screen buffer * @damage_lock: spinlock protecting @damage_clip + * @damage_work: worker used to flush the framebuffer * @resume_work: worker used during resume if the console lock is already taken * * This is the main structure used by the fbdev helpers. Drivers supporting @@ -145,6 +146,7 @@ struct drm_fb_helper { u32 pseudo_palette[17]; struct drm_clip_rect damage_clip; spinlock_t damage_lock; + struct work_struct damage_work; struct work_struct resume_work; /** -- cgit v1.2.3 From 8b83e1a455382dc667898a525a93f4eb6716cc41 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 18 Nov 2022 14:35:34 +0100 Subject: Revert "drm/fb-helper: Schedule deferred-I/O worker after writing to framebuffer" This reverts commit 7f5cc4a3e5e4c5a38e5748defc952e45278f7a70. Needed to restore the fbdev damage worker. There have been bug reports about locking order [1] and incorrectly takens branches. [2] Restore the damage worker until these problems have been resovled. Signed-off-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://intel-gfx-ci.01.org/tree/drm-tip/fi-kbl-8809g.html # 1 Link: https://lore.kernel.org/dri-devel/20221115115819.23088-6-tzimmermann@suse.de/T/#m06eedc0a468940e4cbbd14ca026733b639bc445a # 2 Link: https://patchwork.freedesktop.org/patch/msgid/20221118133535.9739-3-tzimmermann@suse.de --- drivers/gpu/drm/drm_fb_helper.c | 9 +-------- drivers/video/fbdev/core/fb_defio.c | 16 ---------------- include/linux/fb.h | 1 - 3 files changed, 1 insertion(+), 25 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index c0e9a977a3b3..cdbf03e941b2 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -599,16 +599,9 @@ static void drm_fb_helper_add_damage_clip(struct drm_fb_helper *helper, u32 x, u static void drm_fb_helper_damage(struct drm_fb_helper *helper, u32 x, u32 y, u32 width, u32 height) { - struct fb_info *info = helper->info; - drm_fb_helper_add_damage_clip(helper, x, y, width, height); - /* - * The current fbdev emulation only flushes buffers if a damage - * update is necessary. And we can assume that deferred I/O has - * been enabled as damage updates require deferred I/O for mmap. - */ - fb_deferred_io_schedule_flush(info); + schedule_work(&helper->damage_work); } /* diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index dec678f72a42..c730253ab85c 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c @@ -332,19 +332,3 @@ void fb_deferred_io_cleanup(struct fb_info *info) mutex_destroy(&fbdefio->lock); } EXPORT_SYMBOL_GPL(fb_deferred_io_cleanup); - -void fb_deferred_io_schedule_flush(struct fb_info *info) -{ - struct fb_deferred_io *fbdefio = info->fbdefio; - - if (WARN_ON_ONCE(!fbdefio)) - return; /* bug in driver logic */ - - /* - * There's no requirement from callers to schedule the - * flush immediately. Rather schedule the worker with a - * delay and let a few more writes pile up. - */ - schedule_delayed_work(&info->deferred_work, fbdefio->delay); -} -EXPORT_SYMBOL_GPL(fb_deferred_io_schedule_flush); diff --git a/include/linux/fb.h b/include/linux/fb.h index a2a52f730989..64889a2b783f 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -663,7 +663,6 @@ extern void fb_deferred_io_open(struct fb_info *info, struct inode *inode, struct file *file); extern void fb_deferred_io_cleanup(struct fb_info *info); -extern void fb_deferred_io_schedule_flush(struct fb_info *info); extern int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasync); -- cgit v1.2.3 From 7df34a619f59439f38e56d389df02ee7e9e8cc97 Mon Sep 17 00:00:00 2001 From: ChunyouTang Date: Sat, 19 Nov 2022 14:41:31 +0800 Subject: drm/gem-shmem: When drm_gem_object_init failed, should release object when goto err_free, the object had init, so it should be release when fail. Signed-off-by: ChunyouTang Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20221119064131.364-1-tangchunyou@163.com --- drivers/gpu/drm/drm_gem.c | 19 ++++++++++++++++--- drivers/gpu/drm/drm_gem_shmem_helper.c | 4 +++- include/drm/drm_gem.h | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index b8db675e7fb5..59a0bb5ebd85 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -169,6 +169,20 @@ void drm_gem_private_object_init(struct drm_device *dev, } EXPORT_SYMBOL(drm_gem_private_object_init); +/** + * drm_gem_private_object_fini - Finalize a failed drm_gem_object + * @obj: drm_gem_object + * + * Uninitialize an already allocated GEM object when it initialized failed + */ +void drm_gem_private_object_fini(struct drm_gem_object *obj) +{ + WARN_ON(obj->dma_buf); + + dma_resv_fini(&obj->_resv); +} +EXPORT_SYMBOL(drm_gem_private_object_fini); + /** * drm_gem_object_handle_free - release resources bound to userspace handles * @obj: GEM object to clean up. @@ -930,12 +944,11 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private) void drm_gem_object_release(struct drm_gem_object *obj) { - WARN_ON(obj->dma_buf); - if (obj->filp) fput(obj->filp); - dma_resv_fini(&obj->_resv); + drm_gem_private_object_fini(obj); + drm_gem_free_mmap_offset(obj); drm_gem_lru_remove(obj); } diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 35138f8a375c..db73234edcbe 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -79,8 +79,10 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private) } else { ret = drm_gem_object_init(dev, obj, size); } - if (ret) + if (ret) { + drm_gem_private_object_fini(obj); goto err_free; + } ret = drm_gem_create_mmap_offset(obj); if (ret) diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index a17c2f903f81..772a4adf5287 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -405,6 +405,7 @@ int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size); void drm_gem_private_object_init(struct drm_device *dev, struct drm_gem_object *obj, size_t size); +void drm_gem_private_object_fini(struct drm_gem_object *obj); void drm_gem_vm_open(struct vm_area_struct *vma); void drm_gem_vm_close(struct vm_area_struct *vma); int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, -- cgit v1.2.3 From b56ffa583350f605446d78cb4163114e4d1ac60c Mon Sep 17 00:00:00 2001 From: "T.J. Mercier" Date: Wed, 23 Nov 2022 19:35:18 +0000 Subject: dma-buf: A collection of typo and documentation fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've been collecting these typo fixes for a while and it feels like time to send them in. Signed-off-by: T.J. Mercier Reviewed-by: Randy Dunlap Acked-by: Christian König Reviewed-by: Tommaso Merciai Link: https://patchwork.freedesktop.org/patch/msgid/20221123193519.3948105-1-tjmercier@google.com Signed-off-by: Christian König --- drivers/dma-buf/dma-buf.c | 14 +++++++------- include/linux/dma-buf.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index b809513b03fe..6277ba3525de 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -1252,7 +1252,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, DMA_BUF); * * @dmabuf: [in] buffer which is moving * - * Informs all attachmenst that they need to destroy and recreated all their + * Informs all attachments that they need to destroy and recreate all their * mappings. */ void dma_buf_move_notify(struct dma_buf *dmabuf) @@ -1270,11 +1270,11 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, DMA_BUF); /** * DOC: cpu access * - * There are mutliple reasons for supporting CPU access to a dma buffer object: + * There are multiple reasons for supporting CPU access to a dma buffer object: * * - Fallback operations in the kernel, for example when a device is connected * over USB and the kernel needs to shuffle the data around first before - * sending it away. Cache coherency is handled by braketing any transactions + * sending it away. Cache coherency is handled by bracketing any transactions * with calls to dma_buf_begin_cpu_access() and dma_buf_end_cpu_access() * access. * @@ -1301,7 +1301,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, DMA_BUF); * replace ION buffers mmap support was needed. * * There is no special interfaces, userspace simply calls mmap on the dma-buf - * fd. But like for CPU access there's a need to braket the actual access, + * fd. But like for CPU access there's a need to bracket the actual access, * which is handled by the ioctl (DMA_BUF_IOCTL_SYNC). Note that * DMA_BUF_IOCTL_SYNC can fail with -EAGAIN or -EINTR, in which case it must * be restarted. @@ -1375,10 +1375,10 @@ static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf, * preparations. Coherency is only guaranteed in the specified range for the * specified access direction. * @dmabuf: [in] buffer to prepare cpu access for. - * @direction: [in] length of range for cpu access. + * @direction: [in] direction of access. * * After the cpu access is complete the caller should call - * dma_buf_end_cpu_access(). Only when cpu access is braketed by both calls is + * dma_buf_end_cpu_access(). Only when cpu access is bracketed by both calls is * it guaranteed to be coherent with other DMA access. * * This function will also wait for any DMA transactions tracked through @@ -1418,7 +1418,7 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_begin_cpu_access, DMA_BUF); * actions. Coherency is only guaranteed in the specified range for the * specified access direction. * @dmabuf: [in] buffer to complete cpu access for. - * @direction: [in] length of range for cpu access. + * @direction: [in] direction of access. * * This terminates CPU access started with dma_buf_begin_cpu_access(). * diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index 6fa8d4e29719..3f31baa3293f 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -356,7 +356,7 @@ struct dma_buf { */ const char *name; - /** @name_lock: Spinlock to protect name acces for read access. */ + /** @name_lock: Spinlock to protect name access for read access. */ spinlock_t name_lock; /** @@ -393,7 +393,7 @@ struct dma_buf { * anything the userspace API considers write access. * * - Drivers may just always add a write fence, since that only - * causes unecessarily synchronization, but no correctness issues. + * causes unnecessary synchronization, but no correctness issues. * * - Some drivers only expose a synchronous userspace API with no * pipelining across drivers. These do not set any fences for their -- cgit v1.2.3 From 1fd4a5a36f9f10aaad5d9b1b329c2c057d80a0e5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Nov 2022 10:28:45 +0100 Subject: drm/connector: Rename legacy TV property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current tv_mode has driver-specific values that don't allow to easily share code using it, either at the userspace or kernel level. Since we're going to introduce a new, generic, property that fit the same purpose, let's rename this one to legacy_tv_mode to make it obvious we should move away from it. Acked-by: Thomas Zimmermann Reviewed-by: Lyude Paul # nouveau Reviewed-by: Noralf Trønnes Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-2-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_uapi.c | 8 ++++---- drivers/gpu/drm/drm_connector.c | 6 +++--- drivers/gpu/drm/gud/gud_connector.c | 6 +++--- drivers/gpu/drm/i2c/ch7006_drv.c | 6 +++--- drivers/gpu/drm/i915/display/intel_tv.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 4 ++-- drivers/gpu/drm/vc4/vc4_vec.c | 8 ++++---- include/drm/drm_connector.h | 4 ++-- include/drm/drm_mode_config.h | 6 ++++-- 9 files changed, 26 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index c06d0639d552..7f2b9a07fbdf 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -698,8 +698,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, state->tv.margins.top = val; } else if (property == config->tv_bottom_margin_property) { state->tv.margins.bottom = val; - } else if (property == config->tv_mode_property) { - state->tv.mode = val; + } else if (property == config->legacy_tv_mode_property) { + state->tv.legacy_mode = val; } else if (property == config->tv_brightness_property) { state->tv.brightness = val; } else if (property == config->tv_contrast_property) { @@ -808,8 +808,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = state->tv.margins.top; } else if (property == config->tv_bottom_margin_property) { *val = state->tv.margins.bottom; - } else if (property == config->tv_mode_property) { - *val = state->tv.mode; + } else if (property == config->legacy_tv_mode_property) { + *val = state->tv.legacy_mode; } else if (property == config->tv_brightness_property) { *val = state->tv.brightness; } else if (property == config->tv_contrast_property) { diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 547356e00341..05edff79d312 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1690,14 +1690,14 @@ int drm_mode_create_tv_properties(struct drm_device *dev, if (drm_mode_create_tv_margin_properties(dev)) goto nomem; - dev->mode_config.tv_mode_property = + dev->mode_config.legacy_tv_mode_property = drm_property_create(dev, DRM_MODE_PROP_ENUM, "mode", num_modes); - if (!dev->mode_config.tv_mode_property) + if (!dev->mode_config.legacy_tv_mode_property) goto nomem; for (i = 0; i < num_modes; i++) - drm_property_add_enum(dev->mode_config.tv_mode_property, + drm_property_add_enum(dev->mode_config.legacy_tv_mode_property, i, modes[i]); dev->mode_config.tv_brightness_property = diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c index fa636206f232..86e992b2108b 100644 --- a/drivers/gpu/drm/gud/gud_connector.c +++ b/drivers/gpu/drm/gud/gud_connector.c @@ -303,7 +303,7 @@ static int gud_connector_atomic_check(struct drm_connector *connector, old_state->tv.margins.right != new_state->tv.margins.right || old_state->tv.margins.top != new_state->tv.margins.top || old_state->tv.margins.bottom != new_state->tv.margins.bottom || - old_state->tv.mode != new_state->tv.mode || + old_state->tv.legacy_mode != new_state->tv.legacy_mode || old_state->tv.brightness != new_state->tv.brightness || old_state->tv.contrast != new_state->tv.contrast || old_state->tv.flicker_reduction != new_state->tv.flicker_reduction || @@ -424,7 +424,7 @@ gud_connector_property_lookup(struct drm_connector *connector, u16 prop) case GUD_PROPERTY_TV_BOTTOM_MARGIN: return config->tv_bottom_margin_property; case GUD_PROPERTY_TV_MODE: - return config->tv_mode_property; + return config->legacy_tv_mode_property; case GUD_PROPERTY_TV_BRIGHTNESS: return config->tv_brightness_property; case GUD_PROPERTY_TV_CONTRAST: @@ -454,7 +454,7 @@ static unsigned int *gud_connector_tv_state_val(u16 prop, struct drm_tv_connecto case GUD_PROPERTY_TV_BOTTOM_MARGIN: return &state->margins.bottom; case GUD_PROPERTY_TV_MODE: - return &state->mode; + return &state->legacy_mode; case GUD_PROPERTY_TV_BRIGHTNESS: return &state->brightness; case GUD_PROPERTY_TV_CONTRAST: diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 578b738859b9..9aff24e8e3b2 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -264,8 +264,8 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder, priv->hmargin); drm_object_attach_property(&connector->base, conf->tv_bottom_margin_property, priv->vmargin); - drm_object_attach_property(&connector->base, conf->tv_mode_property, - priv->norm); + drm_object_attach_property(&connector->base, conf->legacy_tv_mode_property, + priv->norm); drm_object_attach_property(&connector->base, conf->tv_brightness_property, priv->brightness); drm_object_attach_property(&connector->base, conf->tv_contrast_property, @@ -315,7 +315,7 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder, ch7006_load_reg(client, state, CH7006_POV); ch7006_load_reg(client, state, CH7006_VPOS); - } else if (property == conf->tv_mode_property) { + } else if (property == conf->legacy_tv_mode_property) { if (connector->dpms != DRM_MODE_DPMS_OFF) return -EINVAL; diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 4d2101ca1692..5a0483d173d8 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -1908,7 +1908,7 @@ static void intel_tv_add_properties(struct drm_connector *connector) drm_mode_create_tv_properties(&i915->drm, i, tv_format_names); drm_object_attach_property(&connector->base, - i915->drm.mode_config.tv_mode_property, + i915->drm.mode_config.legacy_tv_mode_property, conn_state->tv.mode); drm_object_attach_property(&connector->base, i915->drm.mode_config.tv_left_margin_property, diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index be28e7bd7490..1a15534adc60 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -662,7 +662,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder, conf->tv_subconnector_property, tv_enc->subconnector); drm_object_attach_property(&connector->base, - conf->tv_mode_property, + conf->legacy_tv_mode_property, tv_enc->tv_norm); drm_object_attach_property(&connector->base, conf->tv_flicker_reduction_property, @@ -722,7 +722,7 @@ static int nv17_tv_set_property(struct drm_encoder *encoder, if (encoder->crtc) nv17_tv_update_rescaler(encoder); - } else if (property == conf->tv_mode_property) { + } else if (property == conf->legacy_tv_mode_property) { if (connector->dpms != DRM_MODE_DPMS_OFF) return -EINVAL; diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index 92c07e31d632..e6043cf5d40e 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -274,7 +274,7 @@ static int vc4_vec_connector_get_modes(struct drm_connector *connector) struct drm_display_mode *mode; mode = drm_mode_duplicate(connector->dev, - vc4_vec_tv_modes[state->tv.mode].mode); + vc4_vec_tv_modes[state->tv.legacy_mode].mode); if (!mode) { DRM_ERROR("Failed to create a new display mode\n"); return -ENOMEM; @@ -312,7 +312,7 @@ static int vc4_vec_connector_init(struct drm_device *dev, struct vc4_vec *vec) drm_connector_helper_add(connector, &vc4_vec_connector_helper_funcs); drm_object_attach_property(&connector->base, - dev->mode_config.tv_mode_property, + dev->mode_config.legacy_tv_mode_property, VC4_VEC_TV_MODE_NTSC); drm_connector_attach_encoder(connector, &vec->encoder.base); @@ -361,7 +361,7 @@ static void vc4_vec_encoder_enable(struct drm_encoder *encoder, struct drm_connector_state *conn_state = drm_atomic_get_new_connector_state(state, connector); const struct vc4_vec_tv_mode *tv_mode = - &vc4_vec_tv_modes[conn_state->tv.mode]; + &vc4_vec_tv_modes[conn_state->tv.legacy_mode]; int idx, ret; if (!drm_dev_enter(drm, &idx)) @@ -449,7 +449,7 @@ static int vc4_vec_encoder_atomic_check(struct drm_encoder *encoder, { const struct vc4_vec_tv_mode *vec_mode; - vec_mode = &vc4_vec_tv_modes[conn_state->tv.mode]; + vec_mode = &vc4_vec_tv_modes[conn_state->tv.legacy_mode]; if (conn_state->crtc && !drm_mode_equal(vec_mode->mode, &crtc_state->adjusted_mode)) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 565cf9d3c550..16e47201aaeb 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -701,7 +701,7 @@ struct drm_connector_tv_margins { * @select_subconnector: selected subconnector * @subconnector: detected subconnector * @margins: TV margins - * @mode: TV mode + * @legacy_mode: Legacy TV mode, driver specific value * @brightness: brightness in percent * @contrast: contrast in percent * @flicker_reduction: flicker reduction in percent @@ -713,7 +713,7 @@ struct drm_tv_connector_state { enum drm_mode_subconnector select_subconnector; enum drm_mode_subconnector subconnector; struct drm_connector_tv_margins margins; - unsigned int mode; + unsigned int legacy_mode; unsigned int brightness; unsigned int contrast; unsigned int flicker_reduction; diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index 5362702fffe1..c47b29e80108 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -712,11 +712,13 @@ struct drm_mode_config { * between different TV connector types. */ struct drm_property *tv_select_subconnector_property; + /** - * @tv_mode_property: Optional TV property to select + * @legacy_tv_mode_property: Optional TV property to select * the output TV mode. */ - struct drm_property *tv_mode_property; + struct drm_property *legacy_tv_mode_property; + /** * @tv_left_margin_property: Optional TV property to set the left * margin (expressed in pixels). -- cgit v1.2.3 From 80ed86d4b6d7cf91f4fd588bd7be2fa382724d2d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Nov 2022 10:28:47 +0100 Subject: drm/connector: Rename drm_mode_create_tv_properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drm_mode_create_tv_properties(), among other things, will create the "mode" property that stores the analog TV mode that connector is supposed to output. However, that property is getting deprecated, so let's rename that function to mention it's deprecated. We'll introduce a new variant of that function creating the property superseeding it in a later patch. Reviewed-by: Lyude Paul # nouveau Reviewed-by: Noralf Trønnes Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-4-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_connector.c | 12 ++++++------ drivers/gpu/drm/gud/gud_connector.c | 4 ++-- drivers/gpu/drm/i2c/ch7006_drv.c | 2 +- drivers/gpu/drm/i915/display/intel_tv.c | 2 +- drivers/gpu/drm/nouveau/dispnv04/tvnv17.c | 2 +- drivers/gpu/drm/vc4/vc4_vec.c | 5 +++-- include/drm/drm_connector.h | 6 +++--- 7 files changed, 17 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 78fcffae100b..06e737ed15f5 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1604,7 +1604,7 @@ EXPORT_SYMBOL(drm_connector_attach_tv_margin_properties); * Called by a driver's HDMI connector initialization routine, this function * creates the TV margin properties for a given device. No need to call this * function for an SDTV connector, it's already called from - * drm_mode_create_tv_properties(). + * drm_mode_create_tv_properties_legacy(). * * Returns: * 0 on success or a negative error code on failure. @@ -1639,7 +1639,7 @@ int drm_mode_create_tv_margin_properties(struct drm_device *dev) EXPORT_SYMBOL(drm_mode_create_tv_margin_properties); /** - * drm_mode_create_tv_properties - create TV specific connector properties + * drm_mode_create_tv_properties_legacy - create TV specific connector properties * @dev: DRM device * @num_modes: number of different TV formats (modes) supported * @modes: array of pointers to strings containing name of each format @@ -1652,9 +1652,9 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties); * Returns: * 0 on success or a negative error code on failure. */ -int drm_mode_create_tv_properties(struct drm_device *dev, - unsigned int num_modes, - const char * const modes[]) +int drm_mode_create_tv_properties_legacy(struct drm_device *dev, + unsigned int num_modes, + const char * const modes[]) { struct drm_property *tv_selector; struct drm_property *tv_subconnector; @@ -1737,7 +1737,7 @@ int drm_mode_create_tv_properties(struct drm_device *dev, nomem: return -ENOMEM; } -EXPORT_SYMBOL(drm_mode_create_tv_properties); +EXPORT_SYMBOL(drm_mode_create_tv_properties_legacy); /** * drm_mode_create_scaling_mode_property - create scaling mode property diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c index 86e992b2108b..034e78360d4f 100644 --- a/drivers/gpu/drm/gud/gud_connector.c +++ b/drivers/gpu/drm/gud/gud_connector.c @@ -400,7 +400,7 @@ static int gud_connector_add_tv_mode(struct gud_device *gdrm, struct drm_connect for (i = 0; i < num_modes; i++) modes[i] = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN]; - ret = drm_mode_create_tv_properties(connector->dev, num_modes, modes); + ret = drm_mode_create_tv_properties_legacy(connector->dev, num_modes, modes); free: kfree(buf); if (ret < 0) @@ -539,7 +539,7 @@ static int gud_connector_add_properties(struct gud_device *gdrm, struct gud_conn fallthrough; case GUD_PROPERTY_TV_HUE: /* This is a no-op if already added. */ - ret = drm_mode_create_tv_properties(drm, 0, NULL); + ret = drm_mode_create_tv_properties_legacy(drm, 0, NULL); if (ret) goto out; break; diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 9aff24e8e3b2..b9788218b2ec 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -250,7 +250,7 @@ static int ch7006_encoder_create_resources(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_mode_config *conf = &dev->mode_config; - drm_mode_create_tv_properties(dev, NUM_TV_NORMS, ch7006_tv_norm_names); + drm_mode_create_tv_properties_legacy(dev, NUM_TV_NORMS, ch7006_tv_norm_names); priv->scale_property = drm_property_create_range(dev, 0, "scale", 0, 2); if (!priv->scale_property) diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 5a0483d173d8..b986bf075889 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -1905,7 +1905,7 @@ static void intel_tv_add_properties(struct drm_connector *connector) tv_format_names[i] = tv_modes[i].name; } - drm_mode_create_tv_properties(&i915->drm, i, tv_format_names); + drm_mode_create_tv_properties_legacy(&i915->drm, i, tv_format_names); drm_object_attach_property(&connector->base, i915->drm.mode_config.legacy_tv_mode_property, diff --git a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c index 1a15534adc60..e5480dab55e3 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c +++ b/drivers/gpu/drm/nouveau/dispnv04/tvnv17.c @@ -653,7 +653,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder, tv_enc->tv_norm = i; } - drm_mode_create_tv_properties(dev, num_tv_norms, nv17_tv_norm_names); + drm_mode_create_tv_properties_legacy(dev, num_tv_norms, nv17_tv_norm_names); drm_object_attach_property(&connector->base, conf->tv_select_subconnector_property, diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c index e6043cf5d40e..adc9bf99e3fd 100644 --- a/drivers/gpu/drm/vc4/vc4_vec.c +++ b/drivers/gpu/drm/vc4/vc4_vec.c @@ -514,8 +514,9 @@ static int vc4_vec_bind(struct device *dev, struct device *master, void *data) struct vc4_vec *vec; int ret; - ret = drm_mode_create_tv_properties(drm, ARRAY_SIZE(tv_mode_names), - tv_mode_names); + ret = drm_mode_create_tv_properties_legacy(drm, + ARRAY_SIZE(tv_mode_names), + tv_mode_names); if (ret) return ret; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 16e47201aaeb..572bd6487247 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1820,9 +1820,9 @@ int drm_mode_create_dvi_i_properties(struct drm_device *dev); void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector); int drm_mode_create_tv_margin_properties(struct drm_device *dev); -int drm_mode_create_tv_properties(struct drm_device *dev, - unsigned int num_modes, - const char * const modes[]); +int drm_mode_create_tv_properties_legacy(struct drm_device *dev, + unsigned int num_modes, + const char * const modes[]); void drm_connector_attach_tv_margin_properties(struct drm_connector *conn); int drm_mode_create_scaling_mode_property(struct drm_device *dev); int drm_connector_attach_content_type_property(struct drm_connector *dev); -- cgit v1.2.3 From 7d63cd8526f1b70d1438b1aa90620cde941162c3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Nov 2022 10:28:48 +0100 Subject: drm/connector: Add TV standard property The TV mode property has been around for a while now to select and get the current TV mode output on an analog TV connector. Despite that property name being generic, its content isn't and has been driver-specific which makes it hard to build any generic behaviour on top of it, both in kernel and user-space. Let's create a new enum tv norm property, that can contain any of the analog TV standards currently supported by kernel drivers. Each driver can then pass in a bitmask of the modes it supports, and the property creation function will filter out the modes not supported. We'll then be able to phase out the older tv mode property. Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-5-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- Documentation/gpu/drm-kms.rst | 6 ++ drivers/gpu/drm/drm_atomic_uapi.c | 4 ++ drivers/gpu/drm/drm_connector.c | 122 +++++++++++++++++++++++++++++++++++++- include/drm/drm_connector.h | 64 ++++++++++++++++++++ include/drm/drm_mode_config.h | 8 +++ 5 files changed, 203 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/gpu/drm-kms.rst b/Documentation/gpu/drm-kms.rst index b4377a545425..321f2f582c64 100644 --- a/Documentation/gpu/drm-kms.rst +++ b/Documentation/gpu/drm-kms.rst @@ -520,6 +520,12 @@ HDMI Specific Connector Properties .. kernel-doc:: drivers/gpu/drm/drm_connector.c :doc: HDMI connector properties +Analog TV Specific Connector Properties +---------------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_connector.c + :doc: Analog TV Connector Properties + Standard CRTC Properties ------------------------ diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 7f2b9a07fbdf..d867e7f9f2cd 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -700,6 +700,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, state->tv.margins.bottom = val; } else if (property == config->legacy_tv_mode_property) { state->tv.legacy_mode = val; + } else if (property == config->tv_mode_property) { + state->tv.mode = val; } else if (property == config->tv_brightness_property) { state->tv.brightness = val; } else if (property == config->tv_contrast_property) { @@ -810,6 +812,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, *val = state->tv.margins.bottom; } else if (property == config->legacy_tv_mode_property) { *val = state->tv.legacy_mode; + } else if (property == config->tv_mode_property) { + *val = state->tv.mode; } else if (property == config->tv_brightness_property) { *val = state->tv.brightness; } else if (property == config->tv_contrast_property) { diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 06e737ed15f5..07d449736956 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -984,6 +984,17 @@ static const struct drm_prop_enum_list drm_dvi_i_subconnector_enum_list[] = { DRM_ENUM_NAME_FN(drm_get_dvi_i_subconnector_name, drm_dvi_i_subconnector_enum_list) +static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = { + { DRM_MODE_TV_MODE_NTSC, "NTSC" }, + { DRM_MODE_TV_MODE_NTSC_443, "NTSC-443" }, + { DRM_MODE_TV_MODE_NTSC_J, "NTSC-J" }, + { DRM_MODE_TV_MODE_PAL, "PAL" }, + { DRM_MODE_TV_MODE_PAL_M, "PAL-M" }, + { DRM_MODE_TV_MODE_PAL_N, "PAL-N" }, + { DRM_MODE_TV_MODE_SECAM, "SECAM" }, +}; +DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list) + static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ @@ -1552,6 +1563,71 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property); * infoframe values is done through drm_hdmi_avi_infoframe_content_type(). */ +/* + * TODO: Document the properties: + * - left margin + * - right margin + * - top margin + * - bottom margin + * - brightness + * - contrast + * - flicker reduction + * - hue + * - mode + * - overscan + * - saturation + * - select subconnector + * - subconnector + */ +/** + * DOC: Analog TV Connector Properties + * + * TV Mode: + * Indicates the TV Mode used on an analog TV connector. The value + * of this property can be one of the following: + * + * NTSC: + * TV Mode is CCIR System M (aka 525-lines) together with + * the NTSC Color Encoding. + * + * NTSC-443: + * + * TV Mode is CCIR System M (aka 525-lines) together with + * the NTSC Color Encoding, but with a color subcarrier + * frequency of 4.43MHz + * + * NTSC-J: + * + * TV Mode is CCIR System M (aka 525-lines) together with + * the NTSC Color Encoding, but with a black level equal to + * the blanking level. + * + * PAL: + * + * TV Mode is CCIR System B (aka 625-lines) together with + * the PAL Color Encoding. + * + * PAL-M: + * + * TV Mode is CCIR System M (aka 525-lines) together with + * the PAL Color Encoding. + * + * PAL-N: + * + * TV Mode is CCIR System N together with the PAL Color + * Encoding, a color subcarrier frequency of 3.58MHz, the + * SECAM color space, and narrower channels than other PAL + * variants. + * + * SECAM: + * + * TV Mode is CCIR System B (aka 625-lines) together with + * the SECAM Color Encoding. + * + * Drivers can set up this property by calling + * drm_mode_create_tv_properties(). + */ + /** * drm_connector_attach_content_type_property - attach content-type property * @connector: connector to attach content type property on. @@ -1649,6 +1725,10 @@ EXPORT_SYMBOL(drm_mode_create_tv_margin_properties); * responsible for allocating a list of format names and passing them to * this routine. * + * NOTE: This functions registers the deprecated "mode" connector + * property to select the analog TV mode (ie, NTSC, PAL, etc.). New + * drivers must use drm_mode_create_tv_properties() instead. + * * Returns: * 0 on success or a negative error code on failure. */ @@ -1690,7 +1770,6 @@ int drm_mode_create_tv_properties_legacy(struct drm_device *dev, if (drm_mode_create_tv_margin_properties(dev)) goto nomem; - if (num_modes) { dev->mode_config.legacy_tv_mode_property = drm_property_create(dev, DRM_MODE_PROP_ENUM, @@ -1739,6 +1818,47 @@ nomem: } EXPORT_SYMBOL(drm_mode_create_tv_properties_legacy); +/** + * drm_mode_create_tv_properties - create TV specific connector properties + * @dev: DRM device + * @supported_tv_modes: Bitmask of TV modes supported (See DRM_MODE_TV_MODE_*) + + * Called by a driver's TV initialization routine, this function creates + * the TV specific connector properties for a given device. + * + * Returns: + * 0 on success or a negative error code on failure. + */ +int drm_mode_create_tv_properties(struct drm_device *dev, + unsigned int supported_tv_modes) +{ + struct drm_prop_enum_list tv_mode_list[DRM_MODE_TV_MODE_MAX]; + struct drm_property *tv_mode; + unsigned int i, len = 0; + + if (dev->mode_config.tv_mode_property) + return 0; + + for (i = 0; i < DRM_MODE_TV_MODE_MAX; i++) { + if (!(supported_tv_modes & BIT(i))) + continue; + + tv_mode_list[len].type = i; + tv_mode_list[len].name = drm_get_tv_mode_name(i); + len++; + } + + tv_mode = drm_property_create_enum(dev, 0, "TV mode", + tv_mode_list, len); + if (!tv_mode) + return -ENOMEM; + + dev->mode_config.tv_mode_property = tv_mode; + + return drm_mode_create_tv_properties_legacy(dev, 0, NULL); +} +EXPORT_SYMBOL(drm_mode_create_tv_properties); + /** * drm_mode_create_scaling_mode_property - create scaling mode property * @dev: DRM device diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 572bd6487247..efa32e88a5b7 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -143,6 +143,65 @@ enum subpixel_order { }; +/** + * enum drm_connector_tv_mode - Analog TV output mode + * + * This enum is used to indicate the TV output mode used on an analog TV + * connector. + * + * WARNING: The values of this enum is uABI since they're exposed in the + * "TV mode" connector property. + */ +enum drm_connector_tv_mode { + /** + * @DRM_MODE_TV_MODE_NTSC: CCIR System M (aka 525-lines) + * together with the NTSC Color Encoding. + */ + DRM_MODE_TV_MODE_NTSC, + + /** + * @DRM_MODE_TV_MODE_NTSC_443: Variant of + * @DRM_MODE_TV_MODE_NTSC. Uses a color subcarrier frequency + * of 4.43 MHz. + */ + DRM_MODE_TV_MODE_NTSC_443, + + /** + * @DRM_MODE_TV_MODE_NTSC_J: Variant of @DRM_MODE_TV_MODE_NTSC + * used in Japan. Uses a black level equals to the blanking + * level. + */ + DRM_MODE_TV_MODE_NTSC_J, + + /** + * @DRM_MODE_TV_MODE_PAL: CCIR System B together with the PAL + * color system. + */ + DRM_MODE_TV_MODE_PAL, + + /** + * @DRM_MODE_TV_MODE_PAL_M: CCIR System M (aka 525-lines) + * together with the PAL color encoding + */ + DRM_MODE_TV_MODE_PAL_M, + + /** + * @DRM_MODE_TV_MODE_PAL_N: CCIR System N together with the PAL + * color encoding. It uses 625 lines, but has a color subcarrier + * frequency of 3.58MHz, the SECAM color space, and narrower + * channels compared to most of the other PAL variants. + */ + DRM_MODE_TV_MODE_PAL_N, + + /** + * @DRM_MODE_TV_MODE_SECAM: CCIR System B together with the + * SECAM color system. + */ + DRM_MODE_TV_MODE_SECAM, + + DRM_MODE_TV_MODE_MAX, +}; + /** * struct drm_scrambling: sink's scrambling support. */ @@ -702,6 +761,7 @@ struct drm_connector_tv_margins { * @subconnector: detected subconnector * @margins: TV margins * @legacy_mode: Legacy TV mode, driver specific value + * @mode: TV mode * @brightness: brightness in percent * @contrast: contrast in percent * @flicker_reduction: flicker reduction in percent @@ -714,6 +774,7 @@ struct drm_tv_connector_state { enum drm_mode_subconnector subconnector; struct drm_connector_tv_margins margins; unsigned int legacy_mode; + unsigned int mode; unsigned int brightness; unsigned int contrast; unsigned int flicker_reduction; @@ -1810,6 +1871,7 @@ const char *drm_get_subpixel_order_name(enum subpixel_order order); const char *drm_get_dpms_name(int val); const char *drm_get_dvi_i_subconnector_name(int val); const char *drm_get_dvi_i_select_name(int val); +const char *drm_get_tv_mode_name(int val); const char *drm_get_tv_subconnector_name(int val); const char *drm_get_tv_select_name(int val); const char *drm_get_dp_subconnector_name(int val); @@ -1823,6 +1885,8 @@ int drm_mode_create_tv_margin_properties(struct drm_device *dev); int drm_mode_create_tv_properties_legacy(struct drm_device *dev, unsigned int num_modes, const char * const modes[]); +int drm_mode_create_tv_properties(struct drm_device *dev, + unsigned int supported_tv_modes); void drm_connector_attach_tv_margin_properties(struct drm_connector *conn); int drm_mode_create_scaling_mode_property(struct drm_device *dev); int drm_connector_attach_content_type_property(struct drm_connector *dev); diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h index c47b29e80108..e5b053001d22 100644 --- a/include/drm/drm_mode_config.h +++ b/include/drm/drm_mode_config.h @@ -716,9 +716,17 @@ struct drm_mode_config { /** * @legacy_tv_mode_property: Optional TV property to select * the output TV mode. + * + * Superseded by @tv_mode_property */ struct drm_property *legacy_tv_mode_property; + /** + * @tv_mode_property: Optional TV property to select the TV + * standard output on the connector. + */ + struct drm_property *tv_mode_property; + /** * @tv_left_margin_property: Optional TV property to set the left * margin (expressed in pixels). -- cgit v1.2.3 From 4fcd238560ee6724d6edcae95820bdf7f2e40ab1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Nov 2022 10:28:49 +0100 Subject: drm/modes: Add a function to generate analog display modes Multiple drivers (meson, vc4, sun4i) define analog TV 525-lines and 625-lines modes in their drivers. Since those modes are fairly standard, and that we'll need to use them in more places in the future, it makes sense to move their definition into the core framework. However, analog display usually have fairly loose timings requirements, the only discrete parameters being the total number of lines and pixel clock frequency. Thus, we created a function that will create a display mode from the standard, the pixel frequency and the active area. Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-6-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_modes.c | 476 +++++++++++++++++++++++++++++++++ drivers/gpu/drm/tests/Makefile | 1 + drivers/gpu/drm/tests/drm_modes_test.c | 145 ++++++++++ include/drm/drm_modes.h | 17 ++ 4 files changed, 639 insertions(+) create mode 100644 drivers/gpu/drm/tests/drm_modes_test.c (limited to 'include') diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 3c8034a8c27b..9426c87df623 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -116,6 +116,482 @@ void drm_mode_probed_add(struct drm_connector *connector, } EXPORT_SYMBOL(drm_mode_probed_add); +enum drm_mode_analog { + DRM_MODE_ANALOG_NTSC, /* 525 lines, 60Hz */ + DRM_MODE_ANALOG_PAL, /* 625 lines, 50Hz */ +}; + +/* + * The timings come from: + * - https://web.archive.org/web/20220406232708/http://www.kolumbus.fi/pami1/video/pal_ntsc.html + * - https://web.archive.org/web/20220406124914/http://martin.hinner.info/vga/pal.html + * - https://web.archive.org/web/20220609202433/http://www.batsocks.co.uk/readme/video_timing.htm + */ +#define NTSC_LINE_DURATION_NS 63556U +#define NTSC_LINES_NUMBER 525 + +#define NTSC_HBLK_DURATION_TYP_NS 10900U +#define NTSC_HBLK_DURATION_MIN_NS (NTSC_HBLK_DURATION_TYP_NS - 200) +#define NTSC_HBLK_DURATION_MAX_NS (NTSC_HBLK_DURATION_TYP_NS + 200) + +#define NTSC_HACT_DURATION_TYP_NS (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_TYP_NS) +#define NTSC_HACT_DURATION_MIN_NS (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MAX_NS) +#define NTSC_HACT_DURATION_MAX_NS (NTSC_LINE_DURATION_NS - NTSC_HBLK_DURATION_MIN_NS) + +#define NTSC_HFP_DURATION_TYP_NS 1500 +#define NTSC_HFP_DURATION_MIN_NS 1270 +#define NTSC_HFP_DURATION_MAX_NS 2220 + +#define NTSC_HSLEN_DURATION_TYP_NS 4700 +#define NTSC_HSLEN_DURATION_MIN_NS (NTSC_HSLEN_DURATION_TYP_NS - 100) +#define NTSC_HSLEN_DURATION_MAX_NS (NTSC_HSLEN_DURATION_TYP_NS + 100) + +#define NTSC_HBP_DURATION_TYP_NS 4700 + +/* + * I couldn't find the actual tolerance for the back porch, so let's + * just reuse the sync length ones. + */ +#define NTSC_HBP_DURATION_MIN_NS (NTSC_HBP_DURATION_TYP_NS - 100) +#define NTSC_HBP_DURATION_MAX_NS (NTSC_HBP_DURATION_TYP_NS + 100) + +#define PAL_LINE_DURATION_NS 64000U +#define PAL_LINES_NUMBER 625 + +#define PAL_HACT_DURATION_TYP_NS 51950U +#define PAL_HACT_DURATION_MIN_NS (PAL_HACT_DURATION_TYP_NS - 100) +#define PAL_HACT_DURATION_MAX_NS (PAL_HACT_DURATION_TYP_NS + 400) + +#define PAL_HBLK_DURATION_TYP_NS (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_TYP_NS) +#define PAL_HBLK_DURATION_MIN_NS (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MAX_NS) +#define PAL_HBLK_DURATION_MAX_NS (PAL_LINE_DURATION_NS - PAL_HACT_DURATION_MIN_NS) + +#define PAL_HFP_DURATION_TYP_NS 1650 +#define PAL_HFP_DURATION_MIN_NS (PAL_HFP_DURATION_TYP_NS - 100) +#define PAL_HFP_DURATION_MAX_NS (PAL_HFP_DURATION_TYP_NS + 400) + +#define PAL_HSLEN_DURATION_TYP_NS 4700 +#define PAL_HSLEN_DURATION_MIN_NS (PAL_HSLEN_DURATION_TYP_NS - 200) +#define PAL_HSLEN_DURATION_MAX_NS (PAL_HSLEN_DURATION_TYP_NS + 200) + +#define PAL_HBP_DURATION_TYP_NS 5700 +#define PAL_HBP_DURATION_MIN_NS (PAL_HBP_DURATION_TYP_NS - 200) +#define PAL_HBP_DURATION_MAX_NS (PAL_HBP_DURATION_TYP_NS + 200) + +struct analog_param_field { + unsigned int even, odd; +}; + +#define PARAM_FIELD(_odd, _even) \ + { .even = _even, .odd = _odd } + +struct analog_param_range { + unsigned int min, typ, max; +}; + +#define PARAM_RANGE(_min, _typ, _max) \ + { .min = _min, .typ = _typ, .max = _max } + +struct analog_parameters { + unsigned int num_lines; + unsigned int line_duration_ns; + + struct analog_param_range hact_ns; + struct analog_param_range hfp_ns; + struct analog_param_range hslen_ns; + struct analog_param_range hbp_ns; + struct analog_param_range hblk_ns; + + unsigned int bt601_hfp; + + struct analog_param_field vfp_lines; + struct analog_param_field vslen_lines; + struct analog_param_field vbp_lines; +}; + +#define TV_MODE_PARAMETER(_mode, _lines, _line_dur, _hact, _hfp, \ + _hslen, _hbp, _hblk, _bt601_hfp, _vfp, \ + _vslen, _vbp) \ + [_mode] = { \ + .num_lines = _lines, \ + .line_duration_ns = _line_dur, \ + .hact_ns = _hact, \ + .hfp_ns = _hfp, \ + .hslen_ns = _hslen, \ + .hbp_ns = _hbp, \ + .hblk_ns = _hblk, \ + .bt601_hfp = _bt601_hfp, \ + .vfp_lines = _vfp, \ + .vslen_lines = _vslen, \ + .vbp_lines = _vbp, \ + } + +static const struct analog_parameters tv_modes_parameters[] = { + TV_MODE_PARAMETER(DRM_MODE_ANALOG_NTSC, + NTSC_LINES_NUMBER, + NTSC_LINE_DURATION_NS, + PARAM_RANGE(NTSC_HACT_DURATION_MIN_NS, + NTSC_HACT_DURATION_TYP_NS, + NTSC_HACT_DURATION_MAX_NS), + PARAM_RANGE(NTSC_HFP_DURATION_MIN_NS, + NTSC_HFP_DURATION_TYP_NS, + NTSC_HFP_DURATION_MAX_NS), + PARAM_RANGE(NTSC_HSLEN_DURATION_MIN_NS, + NTSC_HSLEN_DURATION_TYP_NS, + NTSC_HSLEN_DURATION_MAX_NS), + PARAM_RANGE(NTSC_HBP_DURATION_MIN_NS, + NTSC_HBP_DURATION_TYP_NS, + NTSC_HBP_DURATION_MAX_NS), + PARAM_RANGE(NTSC_HBLK_DURATION_MIN_NS, + NTSC_HBLK_DURATION_TYP_NS, + NTSC_HBLK_DURATION_MAX_NS), + 16, + PARAM_FIELD(3, 3), + PARAM_FIELD(3, 3), + PARAM_FIELD(16, 17)), + TV_MODE_PARAMETER(DRM_MODE_ANALOG_PAL, + PAL_LINES_NUMBER, + PAL_LINE_DURATION_NS, + PARAM_RANGE(PAL_HACT_DURATION_MIN_NS, + PAL_HACT_DURATION_TYP_NS, + PAL_HACT_DURATION_MAX_NS), + PARAM_RANGE(PAL_HFP_DURATION_MIN_NS, + PAL_HFP_DURATION_TYP_NS, + PAL_HFP_DURATION_MAX_NS), + PARAM_RANGE(PAL_HSLEN_DURATION_MIN_NS, + PAL_HSLEN_DURATION_TYP_NS, + PAL_HSLEN_DURATION_MAX_NS), + PARAM_RANGE(PAL_HBP_DURATION_MIN_NS, + PAL_HBP_DURATION_TYP_NS, + PAL_HBP_DURATION_MAX_NS), + PARAM_RANGE(PAL_HBLK_DURATION_MIN_NS, + PAL_HBLK_DURATION_TYP_NS, + PAL_HBLK_DURATION_MAX_NS), + 12, + + /* + * The front porch is actually 6 short sync + * pulses for the even field, and 5 for the + * odd field. Each sync takes half a life so + * the odd field front porch is shorter by + * half a line. + * + * In progressive, we're supposed to use 6 + * pulses, so we're fine there + */ + PARAM_FIELD(3, 2), + + /* + * The vsync length is 5 long sync pulses, + * each field taking half a line. We're + * shorter for both fields by half a line. + * + * In progressive, we're supposed to use 5 + * pulses, so we're off by half + * a line. + * + * In interlace, we're now off by half a line + * for the even field and one line for the odd + * field. + */ + PARAM_FIELD(3, 3), + + /* + * The back porch starts with post-equalizing + * pulses, consisting in 5 short sync pulses + * for the even field, 4 for the odd field. In + * progressive, it's 5 short syncs. + * + * In progressive, we thus have 2.5 lines, + * plus the 0.5 line we were missing + * previously, so we should use 3 lines. + * + * In interlace, the even field is in the + * exact same case than progressive. For the + * odd field, we should be using 2 lines but + * we're one line short, so we'll make up for + * it here by using 3. + * + * The entire blanking area is supposed to + * take 25 lines, so we also need to account + * for the rest of the blanking area that + * can't be in either the front porch or sync + * period. + */ + PARAM_FIELD(19, 20)), +}; + +static int fill_analog_mode(struct drm_device *dev, + struct drm_display_mode *mode, + const struct analog_parameters *params, + unsigned long pixel_clock_hz, + unsigned int hactive, + unsigned int vactive, + bool interlace) +{ + unsigned long pixel_duration_ns = NSEC_PER_SEC / pixel_clock_hz; + unsigned int htotal, vtotal; + unsigned int max_hact, hact_duration_ns; + unsigned int hblk, hblk_duration_ns; + unsigned int hfp, hfp_duration_ns; + unsigned int hslen, hslen_duration_ns; + unsigned int hbp, hbp_duration_ns; + unsigned int porches, porches_duration_ns; + unsigned int vfp, vfp_min; + unsigned int vbp, vbp_min; + unsigned int vslen; + bool bt601 = false; + int porches_rem; + u64 result; + + drm_dbg_kms(dev, + "Generating a %ux%u%c, %u-line mode with a %lu kHz clock\n", + hactive, vactive, + interlace ? 'i' : 'p', + params->num_lines, + pixel_clock_hz / 1000); + + max_hact = params->hact_ns.max / pixel_duration_ns; + if (pixel_clock_hz == 13500000 && hactive > max_hact && hactive <= 720) { + drm_dbg_kms(dev, "Trying to generate a BT.601 mode. Disabling checks.\n"); + bt601 = true; + } + + /* + * Our pixel duration is going to be round down by the division, + * so rounding up is probably going to introduce even more + * deviation. + */ + result = (u64)params->line_duration_ns * pixel_clock_hz; + do_div(result, NSEC_PER_SEC); + htotal = result; + + drm_dbg_kms(dev, "Total Horizontal Number of Pixels: %u\n", htotal); + + hact_duration_ns = hactive * pixel_duration_ns; + if (!bt601 && + (hact_duration_ns < params->hact_ns.min || + hact_duration_ns > params->hact_ns.max)) { + DRM_ERROR("Invalid horizontal active area duration: %uns (min: %u, max %u)\n", + hact_duration_ns, params->hact_ns.min, params->hact_ns.max); + return -EINVAL; + } + + hblk = htotal - hactive; + drm_dbg_kms(dev, "Horizontal Blanking Period: %u\n", hblk); + + hblk_duration_ns = hblk * pixel_duration_ns; + if (!bt601 && + (hblk_duration_ns < params->hblk_ns.min || + hblk_duration_ns > params->hblk_ns.max)) { + DRM_ERROR("Invalid horizontal blanking duration: %uns (min: %u, max %u)\n", + hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max); + return -EINVAL; + } + + hslen = DIV_ROUND_UP(params->hslen_ns.typ, pixel_duration_ns); + drm_dbg_kms(dev, "Horizontal Sync Period: %u\n", hslen); + + hslen_duration_ns = hslen * pixel_duration_ns; + if (!bt601 && + (hslen_duration_ns < params->hslen_ns.min || + hslen_duration_ns > params->hslen_ns.max)) { + DRM_ERROR("Invalid horizontal sync duration: %uns (min: %u, max %u)\n", + hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max); + return -EINVAL; + } + + porches = hblk - hslen; + drm_dbg_kms(dev, "Remaining horizontal pixels for both porches: %u\n", porches); + + porches_duration_ns = porches * pixel_duration_ns; + if (!bt601 && + (porches_duration_ns > (params->hfp_ns.max + params->hbp_ns.max) || + porches_duration_ns < (params->hfp_ns.min + params->hbp_ns.min))) { + DRM_ERROR("Invalid horizontal porches duration: %uns\n", porches_duration_ns); + return -EINVAL; + } + + if (bt601) { + hfp = params->bt601_hfp; + } else { + unsigned int hfp_min = DIV_ROUND_UP(params->hfp_ns.min, + pixel_duration_ns); + unsigned int hbp_min = DIV_ROUND_UP(params->hbp_ns.min, + pixel_duration_ns); + int porches_rem = porches - hfp_min - hbp_min; + + hfp = hfp_min + DIV_ROUND_UP(porches_rem, 2); + } + + drm_dbg_kms(dev, "Horizontal Front Porch: %u\n", hfp); + + hfp_duration_ns = hfp * pixel_duration_ns; + if (!bt601 && + (hfp_duration_ns < params->hfp_ns.min || + hfp_duration_ns > params->hfp_ns.max)) { + DRM_ERROR("Invalid horizontal front porch duration: %uns (min: %u, max %u)\n", + hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max); + return -EINVAL; + } + + hbp = porches - hfp; + drm_dbg_kms(dev, "Horizontal Back Porch: %u\n", hbp); + + hbp_duration_ns = hbp * pixel_duration_ns; + if (!bt601 && + (hbp_duration_ns < params->hbp_ns.min || + hbp_duration_ns > params->hbp_ns.max)) { + DRM_ERROR("Invalid horizontal back porch duration: %uns (min: %u, max %u)\n", + hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max); + return -EINVAL; + } + + if (htotal != (hactive + hfp + hslen + hbp)) + return -EINVAL; + + mode->clock = pixel_clock_hz / 1000; + mode->hdisplay = hactive; + mode->hsync_start = mode->hdisplay + hfp; + mode->hsync_end = mode->hsync_start + hslen; + mode->htotal = mode->hsync_end + hbp; + + if (interlace) { + vfp_min = params->vfp_lines.even + params->vfp_lines.odd; + vbp_min = params->vbp_lines.even + params->vbp_lines.odd; + vslen = params->vslen_lines.even + params->vslen_lines.odd; + } else { + /* + * By convention, NTSC (aka 525/60) systems start with + * the even field, but PAL (aka 625/50) systems start + * with the odd one. + * + * PAL systems also have asymmetric timings between the + * even and odd field, while NTSC is symmetric. + * + * Moreover, if we want to create a progressive mode for + * PAL, we need to use the odd field timings. + * + * Since odd == even for NTSC, we can just use the odd + * one all the time to simplify the code a bit. + */ + vfp_min = params->vfp_lines.odd; + vbp_min = params->vbp_lines.odd; + vslen = params->vslen_lines.odd; + } + + drm_dbg_kms(dev, "Vertical Sync Period: %u\n", vslen); + + porches = params->num_lines - vactive - vslen; + drm_dbg_kms(dev, "Remaining vertical pixels for both porches: %u\n", porches); + + porches_rem = porches - vfp_min - vbp_min; + vfp = vfp_min + (porches_rem / 2); + drm_dbg_kms(dev, "Vertical Front Porch: %u\n", vfp); + + vbp = porches - vfp; + drm_dbg_kms(dev, "Vertical Back Porch: %u\n", vbp); + + vtotal = vactive + vfp + vslen + vbp; + if (params->num_lines != vtotal) { + DRM_ERROR("Invalid vertical total: %upx (expected %upx)\n", + vtotal, params->num_lines); + return -EINVAL; + } + + mode->vdisplay = vactive; + mode->vsync_start = mode->vdisplay + vfp; + mode->vsync_end = mode->vsync_start + vslen; + mode->vtotal = mode->vsync_end + vbp; + + if (mode->vtotal != params->num_lines) + return -EINVAL; + + mode->type = DRM_MODE_TYPE_DRIVER; + mode->flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC; + if (interlace) + mode->flags |= DRM_MODE_FLAG_INTERLACE; + + drm_mode_set_name(mode); + + drm_dbg_kms(dev, "Generated mode " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); + + return 0; +} + +/** + * drm_analog_tv_mode - create a display mode for an analog TV + * @dev: drm device + * @tv_mode: TV Mode standard to create a mode for. See DRM_MODE_TV_MODE_*. + * @pixel_clock_hz: Pixel Clock Frequency, in Hertz + * @hdisplay: hdisplay size + * @vdisplay: vdisplay size + * @interlace: whether to compute an interlaced mode + * + * This function creates a struct drm_display_mode instance suited for + * an analog TV output, for one of the usual analog TV mode. + * + * Note that @hdisplay is larger than the usual constraints for the PAL + * and NTSC timings, and we'll choose to ignore most timings constraints + * to reach those resolutions. + * + * Returns: + * + * A pointer to the mode, allocated with drm_mode_create(). Returns NULL + * on error. + */ +struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev, + enum drm_connector_tv_mode tv_mode, + unsigned long pixel_clock_hz, + unsigned int hdisplay, + unsigned int vdisplay, + bool interlace) +{ + struct drm_display_mode *mode; + enum drm_mode_analog analog; + int ret; + + switch (tv_mode) { + case DRM_MODE_TV_MODE_NTSC: + fallthrough; + case DRM_MODE_TV_MODE_NTSC_443: + fallthrough; + case DRM_MODE_TV_MODE_NTSC_J: + fallthrough; + case DRM_MODE_TV_MODE_PAL_M: + analog = DRM_MODE_ANALOG_NTSC; + break; + + case DRM_MODE_TV_MODE_PAL: + fallthrough; + case DRM_MODE_TV_MODE_PAL_N: + fallthrough; + case DRM_MODE_TV_MODE_SECAM: + analog = DRM_MODE_ANALOG_PAL; + break; + + default: + return NULL; + } + + mode = drm_mode_create(dev); + if (!mode) + return NULL; + + ret = fill_analog_mode(dev, mode, + &tv_modes_parameters[analog], + pixel_clock_hz, hdisplay, vdisplay, interlace); + if (ret) + goto err_free_mode; + + return mode; + +err_free_mode: + drm_mode_destroy(dev, mode); + return NULL; +} +EXPORT_SYMBOL(drm_analog_tv_mode); + /** * drm_cvt_mode -create a modeline based on the CVT algorithm * @dev: drm device diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index b29ef1085cad..b22ac96fdd65 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -10,5 +10,6 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \ drm_framebuffer_test.o \ drm_kunit_helpers.o \ drm_mm_test.o \ + drm_modes_test.o \ drm_plane_helper_test.o \ drm_rect_test.o diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c new file mode 100644 index 000000000000..9358a885c58b --- /dev/null +++ b/drivers/gpu/drm/tests/drm_modes_test.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kunit test for drm_modes functions + */ + +#include +#include + +#include + +#include + +#include "drm_kunit_helpers.h" + +struct drm_test_modes_priv { + struct drm_device *drm; +}; + +static int drm_test_modes_init(struct kunit *test) +{ + struct drm_test_modes_priv *priv; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, priv); + + priv->drm = drm_kunit_device_init(test, DRIVER_MODESET, "drm-modes-test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); + + test->priv = priv; + + return 0; +} + +static void drm_test_modes_analog_tv_ntsc_480i(struct kunit *test) +{ + struct drm_test_modes_priv *priv = test->priv; + struct drm_display_mode *mode; + + mode = drm_analog_tv_mode(priv->drm, + DRM_MODE_TV_MODE_NTSC, + 13500 * HZ_PER_KHZ, 720, 480, + true); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 60); + KUNIT_EXPECT_EQ(test, mode->hdisplay, 720); + + /* BT.601 defines hsync_start at 736 for 480i */ + KUNIT_EXPECT_EQ(test, mode->hsync_start, 736); + + /* + * The NTSC standard expects a line to take 63.556us. With a + * pixel clock of 13.5 MHz, a pixel takes around 74ns, so we + * need to have 63556ns / 74ns = 858. + * + * This is also mandated by BT.601. + */ + KUNIT_EXPECT_EQ(test, mode->htotal, 858); + + KUNIT_EXPECT_EQ(test, mode->vdisplay, 480); + KUNIT_EXPECT_EQ(test, mode->vtotal, 525); +} + +static void drm_test_modes_analog_tv_ntsc_480i_inlined(struct kunit *test) +{ + struct drm_test_modes_priv *priv = test->priv; + struct drm_display_mode *expected, *mode; + + expected = drm_analog_tv_mode(priv->drm, + DRM_MODE_TV_MODE_NTSC, + 13500 * HZ_PER_KHZ, 720, 480, + true); + KUNIT_ASSERT_NOT_NULL(test, expected); + + mode = drm_mode_analog_ntsc_480i(priv->drm); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode)); +} + +static void drm_test_modes_analog_tv_pal_576i(struct kunit *test) +{ + struct drm_test_modes_priv *priv = test->priv; + struct drm_display_mode *mode; + + mode = drm_analog_tv_mode(priv->drm, + DRM_MODE_TV_MODE_PAL, + 13500 * HZ_PER_KHZ, 720, 576, + true); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_EXPECT_EQ(test, drm_mode_vrefresh(mode), 50); + KUNIT_EXPECT_EQ(test, mode->hdisplay, 720); + + /* BT.601 defines hsync_start at 732 for 576i */ + KUNIT_EXPECT_EQ(test, mode->hsync_start, 732); + + /* + * The PAL standard expects a line to take 64us. With a pixel + * clock of 13.5 MHz, a pixel takes around 74ns, so we need to + * have 64000ns / 74ns = 864. + * + * This is also mandated by BT.601. + */ + KUNIT_EXPECT_EQ(test, mode->htotal, 864); + + KUNIT_EXPECT_EQ(test, mode->vdisplay, 576); + KUNIT_EXPECT_EQ(test, mode->vtotal, 625); +} + +static void drm_test_modes_analog_tv_pal_576i_inlined(struct kunit *test) +{ + struct drm_test_modes_priv *priv = test->priv; + struct drm_display_mode *expected, *mode; + + expected = drm_analog_tv_mode(priv->drm, + DRM_MODE_TV_MODE_PAL, + 13500 * HZ_PER_KHZ, 720, 576, + true); + KUNIT_ASSERT_NOT_NULL(test, expected); + + mode = drm_mode_analog_pal_576i(priv->drm); + KUNIT_ASSERT_NOT_NULL(test, mode); + + KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected, mode)); +} + +static struct kunit_case drm_modes_analog_tv_tests[] = { + KUNIT_CASE(drm_test_modes_analog_tv_ntsc_480i), + KUNIT_CASE(drm_test_modes_analog_tv_ntsc_480i_inlined), + KUNIT_CASE(drm_test_modes_analog_tv_pal_576i), + KUNIT_CASE(drm_test_modes_analog_tv_pal_576i_inlined), + { } +}; + +static struct kunit_suite drm_modes_analog_tv_test_suite = { + .name = "drm_modes_analog_tv", + .init = drm_test_modes_init, + .test_cases = drm_modes_analog_tv_tests, +}; + +kunit_test_suite(drm_modes_analog_tv_test_suite); + +MODULE_AUTHOR("Maxime Ripard "); +MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index b0c680e6f670..c613f0abe9dc 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -468,6 +468,23 @@ bool drm_mode_is_420_also(const struct drm_display_info *display, bool drm_mode_is_420(const struct drm_display_info *display, const struct drm_display_mode *mode); +struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev, + enum drm_connector_tv_mode mode, + unsigned long pixel_clock_hz, + unsigned int hdisplay, + unsigned int vdisplay, + bool interlace); + +static inline struct drm_display_mode *drm_mode_analog_ntsc_480i(struct drm_device *dev) +{ + return drm_analog_tv_mode(dev, DRM_MODE_TV_MODE_NTSC, 13500000, 720, 480, true); +} + +static inline struct drm_display_mode *drm_mode_analog_pal_576i(struct drm_device *dev) +{ + return drm_analog_tv_mode(dev, DRM_MODE_TV_MODE_PAL, 13500000, 720, 576, true); +} + struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool reduced, bool interlaced, -- cgit v1.2.3 From d4613e3e50d34bc30ea384b8bf9560e874451640 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Nov 2022 10:28:50 +0100 Subject: drm/connector: Add a function to lookup a TV mode by its name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As part of the command line parsing rework coming in the next patches, we'll need to lookup drm_connector_tv_mode values by their name, already defined in drm_tv_mode_enum_list. In order to avoid any code duplication, let's do a function that will perform a lookup of a TV mode name and return its value. Reviewed-by: Noralf Trønnes Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-7-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_connector.c | 24 ++++++++++ drivers/gpu/drm/tests/Makefile | 1 + drivers/gpu/drm/tests/drm_connector_test.c | 76 ++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 2 + 4 files changed, 103 insertions(+) create mode 100644 drivers/gpu/drm/tests/drm_connector_test.c (limited to 'include') diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 07d449736956..8d92777e57dd 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -995,6 +995,30 @@ static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = { }; DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list) +/** + * drm_get_tv_mode_from_name - Translates a TV mode name into its enum value + * @name: TV Mode name we want to convert + * @len: Length of @name + * + * Translates @name into an enum drm_connector_tv_mode. + * + * Returns: the enum value on success, a negative errno otherwise. + */ +int drm_get_tv_mode_from_name(const char *name, size_t len) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(drm_tv_mode_enum_list); i++) { + const struct drm_prop_enum_list *item = &drm_tv_mode_enum_list[i]; + + if (strlen(item->name) == len && !strncmp(item->name, name, len)) + return item->type; + } + + return -EINVAL; +} +EXPORT_SYMBOL(drm_get_tv_mode_from_name); + static const struct drm_prop_enum_list drm_tv_select_enum_list[] = { { DRM_MODE_SUBCONNECTOR_Automatic, "Automatic" }, /* DVI-I and TV-out */ { DRM_MODE_SUBCONNECTOR_Composite, "Composite" }, /* TV-out */ diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index b22ac96fdd65..c7903c112c65 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \ drm_buddy_test.o \ drm_cmdline_parser_test.o \ + drm_connector_test.o \ drm_damage_helper_test.o \ drm_dp_mst_helper_test.o \ drm_format_helper_test.o \ diff --git a/drivers/gpu/drm/tests/drm_connector_test.c b/drivers/gpu/drm/tests/drm_connector_test.c new file mode 100644 index 000000000000..c66aa2dc8d9d --- /dev/null +++ b/drivers/gpu/drm/tests/drm_connector_test.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kunit test for drm_modes functions + */ + +#include + +#include + +struct drm_get_tv_mode_from_name_test { + const char *name; + enum drm_connector_tv_mode expected_mode; +}; + +#define TV_MODE_NAME(_name, _mode) \ + { \ + .name = _name, \ + .expected_mode = _mode, \ + } + +static void drm_test_get_tv_mode_from_name_valid(struct kunit *test) +{ + const struct drm_get_tv_mode_from_name_test *params = test->param_value; + + KUNIT_EXPECT_EQ(test, + drm_get_tv_mode_from_name(params->name, strlen(params->name)), + params->expected_mode); +} + +static const +struct drm_get_tv_mode_from_name_test drm_get_tv_mode_from_name_valid_tests[] = { + TV_MODE_NAME("NTSC", DRM_MODE_TV_MODE_NTSC), + TV_MODE_NAME("NTSC-443", DRM_MODE_TV_MODE_NTSC_443), + TV_MODE_NAME("NTSC-J", DRM_MODE_TV_MODE_NTSC_J), + TV_MODE_NAME("PAL", DRM_MODE_TV_MODE_PAL), + TV_MODE_NAME("PAL-M", DRM_MODE_TV_MODE_PAL_M), + TV_MODE_NAME("PAL-N", DRM_MODE_TV_MODE_PAL_N), + TV_MODE_NAME("SECAM", DRM_MODE_TV_MODE_SECAM), +}; + +static void +drm_get_tv_mode_from_name_valid_desc(const struct drm_get_tv_mode_from_name_test *t, + char *desc) +{ + sprintf(desc, "%s", t->name); +} + +KUNIT_ARRAY_PARAM(drm_get_tv_mode_from_name_valid, + drm_get_tv_mode_from_name_valid_tests, + drm_get_tv_mode_from_name_valid_desc); + +static void drm_test_get_tv_mode_from_name_truncated(struct kunit *test) +{ + const char *name = "NTS"; + int ret; + + ret = drm_get_tv_mode_from_name(name, strlen(name)); + KUNIT_EXPECT_LT(test, ret, 0); +}; + +static struct kunit_case drm_get_tv_mode_from_name_tests[] = { + KUNIT_CASE_PARAM(drm_test_get_tv_mode_from_name_valid, + drm_get_tv_mode_from_name_valid_gen_params), + KUNIT_CASE(drm_test_get_tv_mode_from_name_truncated), + { } +}; + +static struct kunit_suite drm_get_tv_mode_from_name_test_suite = { + .name = "drm_get_tv_mode_from_name", + .test_cases = drm_get_tv_mode_from_name_tests, +}; + +kunit_test_suite(drm_get_tv_mode_from_name_test_suite); + +MODULE_AUTHOR("Maxime Ripard "); +MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index efa32e88a5b7..3390b93b07e9 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1878,6 +1878,8 @@ const char *drm_get_dp_subconnector_name(int val); const char *drm_get_content_protection_name(int val); const char *drm_get_hdcp_content_type_name(int val); +int drm_get_tv_mode_from_name(const char *name, size_t len); + int drm_mode_create_dvi_i_properties(struct drm_device *dev); void drm_connector_attach_dp_subconnector_property(struct drm_connector *connector); -- cgit v1.2.3 From e691c9992ae1c731ea67083739823b131c1d88ea Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Nov 2022 10:28:51 +0100 Subject: drm/modes: Introduce the tv_mode property as a command-line option MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our new tv mode option allows to specify the TV mode from a property. However, it can still be useful, for example to avoid any boot time artifact, to set that property directly from the kernel command line. Let's add some code to allow it, and some unit tests to exercise that code. Reviewed-by: Noralf Trønnes Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-8-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- Documentation/fb/modedb.rst | 2 + drivers/gpu/drm/drm_modes.c | 37 ++++++++++++-- drivers/gpu/drm/tests/drm_cmdline_parser_test.c | 68 +++++++++++++++++++++++++ include/drm/drm_connector.h | 12 +++++ 4 files changed, 116 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/Documentation/fb/modedb.rst b/Documentation/fb/modedb.rst index e53375033146..bebfe61caa77 100644 --- a/Documentation/fb/modedb.rst +++ b/Documentation/fb/modedb.rst @@ -70,6 +70,8 @@ Valid options are:: - reflect_y (boolean): Perform an axial symmetry on the Y axis - rotate (integer): Rotate the initial framebuffer by x degrees. Valid values are 0, 90, 180 and 270. + - tv_mode: Analog TV mode. One of "NTSC", "NTSC-443", "NTSC-J", "PAL", + "PAL-M", "PAL-N", or "SECAM". - panel_orientation, one of "normal", "upside_down", "left_side_up", or "right_side_up". For KMS drivers only, this sets the "panel orientation" property on the kms connector as hint for kms users. diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 9426c87df623..f9fe065f189b 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -2135,6 +2135,30 @@ static int drm_mode_parse_panel_orientation(const char *delim, return 0; } +static int drm_mode_parse_tv_mode(const char *delim, + struct drm_cmdline_mode *mode) +{ + const char *value; + int ret; + + if (*delim != '=') + return -EINVAL; + + value = delim + 1; + delim = strchr(value, ','); + if (!delim) + delim = value + strlen(value); + + ret = drm_get_tv_mode_from_name(value, delim - value); + if (ret < 0) + return ret; + + mode->tv_mode_specified = true; + mode->tv_mode = ret; + + return 0; +} + static int drm_mode_parse_cmdline_options(const char *str, bool freestanding, const struct drm_connector *connector, @@ -2204,6 +2228,9 @@ static int drm_mode_parse_cmdline_options(const char *str, } else if (!strncmp(option, "panel_orientation", delim - option)) { if (drm_mode_parse_panel_orientation(delim, mode)) return -EINVAL; + } else if (!strncmp(option, "tv_mode", delim - option)) { + if (drm_mode_parse_tv_mode(delim, mode)) + return -EINVAL; } else { return -EINVAL; } @@ -2232,20 +2259,22 @@ struct drm_named_mode { unsigned int xres; unsigned int yres; unsigned int flags; + unsigned int tv_mode; }; -#define NAMED_MODE(_name, _pclk, _x, _y, _flags) \ +#define NAMED_MODE(_name, _pclk, _x, _y, _flags, _mode) \ { \ .name = _name, \ .pixel_clock_khz = _pclk, \ .xres = _x, \ .yres = _y, \ .flags = _flags, \ + .tv_mode = _mode, \ } static const struct drm_named_mode drm_named_modes[] = { - NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE), - NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE), + NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_NTSC), + NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE, DRM_MODE_TV_MODE_PAL), }; static int drm_mode_parse_cmdline_named_mode(const char *name, @@ -2290,6 +2319,8 @@ static int drm_mode_parse_cmdline_named_mode(const char *name, cmdline_mode->xres = mode->xres; cmdline_mode->yres = mode->yres; cmdline_mode->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); + cmdline_mode->tv_mode = mode->tv_mode; + cmdline_mode->tv_mode_specified = true; cmdline_mode->specified = true; return 1; diff --git a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c index 34790e7a3760..88f7f518ffb3 100644 --- a/drivers/gpu/drm/tests/drm_cmdline_parser_test.c +++ b/drivers/gpu/drm/tests/drm_cmdline_parser_test.c @@ -927,6 +927,14 @@ static const struct drm_cmdline_invalid_test drm_cmdline_invalid_tests[] = { .name = "invalid_option", .cmdline = "720x480,test=42", }, + { + .name = "invalid_tv_option", + .cmdline = "720x480i,tv_mode=invalid", + }, + { + .name = "truncated_tv_option", + .cmdline = "720x480i,tv_mode=NTS", + }, }; static void drm_cmdline_invalid_desc(const struct drm_cmdline_invalid_test *t, @@ -937,6 +945,65 @@ static void drm_cmdline_invalid_desc(const struct drm_cmdline_invalid_test *t, KUNIT_ARRAY_PARAM(drm_cmdline_invalid, drm_cmdline_invalid_tests, drm_cmdline_invalid_desc); +struct drm_cmdline_tv_option_test { + const char *name; + const char *cmdline; + struct drm_display_mode *(*mode_fn)(struct drm_device *dev); + enum drm_connector_tv_mode tv_mode; +}; + +static void drm_test_cmdline_tv_options(struct kunit *test) +{ + const struct drm_cmdline_tv_option_test *params = test->param_value; + const struct drm_display_mode *expected_mode = params->mode_fn(NULL); + struct drm_cmdline_mode mode = { }; + + KUNIT_EXPECT_TRUE(test, drm_mode_parse_command_line_for_connector(params->cmdline, + &no_connector, &mode)); + KUNIT_EXPECT_TRUE(test, mode.specified); + KUNIT_EXPECT_EQ(test, mode.xres, expected_mode->hdisplay); + KUNIT_EXPECT_EQ(test, mode.yres, expected_mode->vdisplay); + KUNIT_EXPECT_EQ(test, mode.tv_mode, params->tv_mode); + + KUNIT_EXPECT_FALSE(test, mode.refresh_specified); + + KUNIT_EXPECT_FALSE(test, mode.bpp_specified); + + KUNIT_EXPECT_FALSE(test, mode.rb); + KUNIT_EXPECT_FALSE(test, mode.cvt); + KUNIT_EXPECT_EQ(test, mode.interlace, !!(expected_mode->flags & DRM_MODE_FLAG_INTERLACE)); + KUNIT_EXPECT_FALSE(test, mode.margins); + KUNIT_EXPECT_EQ(test, mode.force, DRM_FORCE_UNSPECIFIED); +} + +#define TV_OPT_TEST(_opt, _cmdline, _mode_fn) \ + { \ + .name = #_opt, \ + .cmdline = _cmdline, \ + .mode_fn = _mode_fn, \ + .tv_mode = DRM_MODE_TV_MODE_ ## _opt, \ + } + +static const struct drm_cmdline_tv_option_test drm_cmdline_tv_option_tests[] = { + TV_OPT_TEST(NTSC, "720x480i,tv_mode=NTSC", drm_mode_analog_ntsc_480i), + TV_OPT_TEST(NTSC_443, "720x480i,tv_mode=NTSC-443", drm_mode_analog_ntsc_480i), + TV_OPT_TEST(NTSC_J, "720x480i,tv_mode=NTSC-J", drm_mode_analog_ntsc_480i), + TV_OPT_TEST(PAL, "720x576i,tv_mode=PAL", drm_mode_analog_pal_576i), + TV_OPT_TEST(PAL_M, "720x480i,tv_mode=PAL-M", drm_mode_analog_ntsc_480i), + TV_OPT_TEST(PAL_N, "720x576i,tv_mode=PAL-N", drm_mode_analog_pal_576i), + TV_OPT_TEST(SECAM, "720x576i,tv_mode=SECAM", drm_mode_analog_pal_576i), +}; + +static void drm_cmdline_tv_option_desc(const struct drm_cmdline_tv_option_test *t, + char *desc) +{ + sprintf(desc, "%s", t->name); +} + +KUNIT_ARRAY_PARAM(drm_cmdline_tv_option, + drm_cmdline_tv_option_tests, + drm_cmdline_tv_option_desc); + static struct kunit_case drm_cmdline_parser_tests[] = { KUNIT_CASE(drm_test_cmdline_force_d_only), KUNIT_CASE(drm_test_cmdline_force_D_only_dvi), @@ -977,6 +1044,7 @@ static struct kunit_case drm_cmdline_parser_tests[] = { KUNIT_CASE(drm_test_cmdline_freestanding_force_e_and_options), KUNIT_CASE(drm_test_cmdline_panel_orientation), KUNIT_CASE_PARAM(drm_test_cmdline_invalid, drm_cmdline_invalid_gen_params), + KUNIT_CASE_PARAM(drm_test_cmdline_tv_options, drm_cmdline_tv_option_gen_params), {} }; diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 3390b93b07e9..9037f1317aee 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1374,6 +1374,18 @@ struct drm_cmdline_mode { * @tv_margins: TV margins to apply to the mode. */ struct drm_connector_tv_margins tv_margins; + + /** + * @tv_mode: TV mode standard. See DRM_MODE_TV_MODE_*. + */ + enum drm_connector_tv_mode tv_mode; + + /** + * @tv_mode_specified: + * + * Did the mode have a preferred TV mode? + */ + bool tv_mode_specified; }; /** -- cgit v1.2.3 From 1e4a91db109f623d0e3ef7d8bfae3c88b4d2fa87 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Thu, 17 Nov 2022 10:28:55 +0100 Subject: drm/probe-helper: Provide a TV get_modes helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the TV connectors will need a similar get_modes implementation that will, depending on the drivers' capabilities, register the 480i and 576i modes. That implementation will also need to set the preferred flag and order the modes based on the driver and users preferrence. This is especially important to guarantee that a userspace stack such as Xorg can start and pick up the preferred mode while maintaining a working output. Signed-off-by: Noralf Trønnes Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-12-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_probe_helper.c | 82 +++++++++++ drivers/gpu/drm/tests/Makefile | 1 + drivers/gpu/drm/tests/drm_probe_helper_test.c | 205 ++++++++++++++++++++++++++ include/drm/drm_probe_helper.h | 1 + 4 files changed, 289 insertions(+) create mode 100644 drivers/gpu/drm/tests/drm_probe_helper_test.c (limited to 'include') diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index bcd9611dabfd..1ea053cef557 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -1146,3 +1146,85 @@ int drm_connector_helper_get_modes(struct drm_connector *connector) return count; } EXPORT_SYMBOL(drm_connector_helper_get_modes); + +/** + * drm_connector_helper_tv_get_modes - Fills the modes availables to a TV connector + * @connector: The connector + * + * Fills the available modes for a TV connector based on the supported + * TV modes, and the default mode expressed by the kernel command line. + * + * This can be used as the default TV connector helper .get_modes() hook + * if the driver does not need any special processing. + * + * Returns: + * The number of modes added to the connector. + */ +int drm_connector_helper_tv_get_modes(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_property *tv_mode_property = + dev->mode_config.tv_mode_property; + struct drm_cmdline_mode *cmdline = &connector->cmdline_mode; + unsigned int ntsc_modes = BIT(DRM_MODE_TV_MODE_NTSC) | + BIT(DRM_MODE_TV_MODE_NTSC_443) | + BIT(DRM_MODE_TV_MODE_NTSC_J) | + BIT(DRM_MODE_TV_MODE_PAL_M); + unsigned int pal_modes = BIT(DRM_MODE_TV_MODE_PAL) | + BIT(DRM_MODE_TV_MODE_PAL_N) | + BIT(DRM_MODE_TV_MODE_SECAM); + unsigned int tv_modes[2] = { UINT_MAX, UINT_MAX }; + unsigned int i, supported_tv_modes = 0; + + if (!tv_mode_property) + return 0; + + for (i = 0; i < tv_mode_property->num_values; i++) + supported_tv_modes |= BIT(tv_mode_property->values[i]); + + if ((supported_tv_modes & ntsc_modes) && + (supported_tv_modes & pal_modes)) { + uint64_t default_mode; + + if (drm_object_property_get_default_value(&connector->base, + tv_mode_property, + &default_mode)) + return 0; + + if (cmdline->tv_mode_specified) + default_mode = cmdline->tv_mode; + + if (BIT(default_mode) & ntsc_modes) { + tv_modes[0] = DRM_MODE_TV_MODE_NTSC; + tv_modes[1] = DRM_MODE_TV_MODE_PAL; + } else { + tv_modes[0] = DRM_MODE_TV_MODE_PAL; + tv_modes[1] = DRM_MODE_TV_MODE_NTSC; + } + } else if (supported_tv_modes & ntsc_modes) { + tv_modes[0] = DRM_MODE_TV_MODE_NTSC; + } else if (supported_tv_modes & pal_modes) { + tv_modes[0] = DRM_MODE_TV_MODE_PAL; + } else { + return 0; + } + + for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { + struct drm_display_mode *mode; + + if (tv_modes[i] == DRM_MODE_TV_MODE_NTSC) + mode = drm_mode_analog_ntsc_480i(dev); + else if (tv_modes[i] == DRM_MODE_TV_MODE_PAL) + mode = drm_mode_analog_pal_576i(dev); + else + break; + if (!mode) + return i; + if (!i) + mode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + } + + return i; +} +EXPORT_SYMBOL(drm_connector_helper_tv_get_modes); diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index c7903c112c65..94fe546d937d 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -13,4 +13,5 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \ drm_mm_test.o \ drm_modes_test.o \ drm_plane_helper_test.o \ + drm_probe_helper_test.o \ drm_rect_test.o diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c new file mode 100644 index 000000000000..7e938258c742 --- /dev/null +++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kunit test for drm_probe_helper functions + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "drm_kunit_helpers.h" + +struct drm_probe_helper_test_priv { + struct drm_device *drm; + struct drm_connector connector; +}; + +static const struct drm_connector_helper_funcs drm_probe_helper_connector_helper_funcs = { +}; + +static const struct drm_connector_funcs drm_probe_helper_connector_funcs = { + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .reset = drm_atomic_helper_connector_reset, +}; + +static int drm_probe_helper_test_init(struct kunit *test) +{ + struct drm_probe_helper_test_priv *priv; + struct drm_connector *connector; + int ret; + + priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, priv); + test->priv = priv; + + priv->drm = drm_kunit_device_init(test, DRIVER_MODESET | DRIVER_ATOMIC, + "drm-probe-helper-test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); + + connector = &priv->connector; + ret = drmm_connector_init(priv->drm, connector, + &drm_probe_helper_connector_funcs, + DRM_MODE_CONNECTOR_Unknown, + NULL); + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_connector_helper_add(connector, &drm_probe_helper_connector_helper_funcs); + + return 0; +} + +typedef struct drm_display_mode *(*expected_mode_func_t)(struct drm_device *); + +struct drm_connector_helper_tv_get_modes_test { + const char *name; + unsigned int supported_tv_modes; + enum drm_connector_tv_mode default_mode; + bool cmdline; + enum drm_connector_tv_mode cmdline_mode; + expected_mode_func_t *expected_modes; + unsigned int num_expected_modes; +}; + +#define _TV_MODE_TEST(_name, _supported, _default, _cmdline, _cmdline_mode, ...) \ + { \ + .name = _name, \ + .supported_tv_modes = _supported, \ + .default_mode = _default, \ + .cmdline = _cmdline, \ + .cmdline_mode = _cmdline_mode, \ + .expected_modes = (expected_mode_func_t[]) { __VA_ARGS__ }, \ + .num_expected_modes = sizeof((expected_mode_func_t[]) { __VA_ARGS__ }) / \ + (sizeof(expected_mode_func_t)), \ + } + +#define TV_MODE_TEST(_name, _supported, _default, ...) \ + _TV_MODE_TEST(_name, _supported, _default, false, 0, __VA_ARGS__) + +#define TV_MODE_TEST_CMDLINE(_name, _supported, _default, _cmdline, ...) \ + _TV_MODE_TEST(_name, _supported, _default, true, _cmdline, __VA_ARGS__) + +static void +drm_test_connector_helper_tv_get_modes_check(struct kunit *test) +{ + const struct drm_connector_helper_tv_get_modes_test *params = test->param_value; + struct drm_probe_helper_test_priv *priv = test->priv; + struct drm_connector *connector = &priv->connector; + struct drm_cmdline_mode *cmdline = &connector->cmdline_mode; + struct drm_display_mode *mode; + const struct drm_display_mode *expected; + size_t len; + int ret; + + if (params->cmdline) { + cmdline->tv_mode_specified = true; + cmdline->tv_mode = params->cmdline_mode; + } + + ret = drm_mode_create_tv_properties(priv->drm, params->supported_tv_modes); + KUNIT_ASSERT_EQ(test, ret, 0); + + drm_object_attach_property(&connector->base, + priv->drm->mode_config.tv_mode_property, + params->default_mode); + + mutex_lock(&priv->drm->mode_config.mutex); + + ret = drm_connector_helper_tv_get_modes(connector); + KUNIT_EXPECT_EQ(test, ret, params->num_expected_modes); + + list_for_each_entry(mode, &connector->probed_modes, head) + len++; + KUNIT_EXPECT_EQ(test, len, params->num_expected_modes); + + if (params->num_expected_modes >= 1) { + mode = list_first_entry_or_null(&connector->probed_modes, + struct drm_display_mode, head); + KUNIT_ASSERT_NOT_NULL(test, mode); + + expected = params->expected_modes[0](priv->drm); + KUNIT_ASSERT_NOT_NULL(test, expected); + + KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected)); + KUNIT_EXPECT_TRUE(test, mode->type & DRM_MODE_TYPE_PREFERRED); + } + + if (params->num_expected_modes >= 2) { + mode = list_next_entry(mode, head); + KUNIT_ASSERT_NOT_NULL(test, mode); + + expected = params->expected_modes[1](priv->drm); + KUNIT_ASSERT_NOT_NULL(test, expected); + + KUNIT_EXPECT_TRUE(test, drm_mode_equal(mode, expected)); + KUNIT_EXPECT_FALSE(test, mode->type & DRM_MODE_TYPE_PREFERRED); + } + + mutex_unlock(&priv->drm->mode_config.mutex); +} + +static const +struct drm_connector_helper_tv_get_modes_test drm_connector_helper_tv_get_modes_tests[] = { + { .name = "None" }, + TV_MODE_TEST("PAL", + BIT(DRM_MODE_TV_MODE_PAL), + DRM_MODE_TV_MODE_PAL, + drm_mode_analog_pal_576i), + TV_MODE_TEST("NTSC", + BIT(DRM_MODE_TV_MODE_NTSC), + DRM_MODE_TV_MODE_NTSC, + drm_mode_analog_ntsc_480i), + TV_MODE_TEST("Both, NTSC Default", + BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL), + DRM_MODE_TV_MODE_NTSC, + drm_mode_analog_ntsc_480i, drm_mode_analog_pal_576i), + TV_MODE_TEST("Both, PAL Default", + BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL), + DRM_MODE_TV_MODE_PAL, + drm_mode_analog_pal_576i, drm_mode_analog_ntsc_480i), + TV_MODE_TEST_CMDLINE("Both, NTSC Default, with PAL on command-line", + BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL), + DRM_MODE_TV_MODE_NTSC, + DRM_MODE_TV_MODE_PAL, + drm_mode_analog_pal_576i, drm_mode_analog_ntsc_480i), + TV_MODE_TEST_CMDLINE("Both, PAL Default, with NTSC on command-line", + BIT(DRM_MODE_TV_MODE_NTSC) | BIT(DRM_MODE_TV_MODE_PAL), + DRM_MODE_TV_MODE_PAL, + DRM_MODE_TV_MODE_NTSC, + drm_mode_analog_ntsc_480i, drm_mode_analog_pal_576i), +}; + +static void +drm_connector_helper_tv_get_modes_desc(const struct drm_connector_helper_tv_get_modes_test *t, + char *desc) +{ + sprintf(desc, "%s", t->name); +} + +KUNIT_ARRAY_PARAM(drm_connector_helper_tv_get_modes, + drm_connector_helper_tv_get_modes_tests, + drm_connector_helper_tv_get_modes_desc); + +static struct kunit_case drm_test_connector_helper_tv_get_modes_tests[] = { + KUNIT_CASE_PARAM(drm_test_connector_helper_tv_get_modes_check, + drm_connector_helper_tv_get_modes_gen_params), + { } +}; + +static struct kunit_suite drm_test_connector_helper_tv_get_modes_suite = { + .name = "drm_connector_helper_tv_get_modes", + .init = drm_probe_helper_test_init, + .test_cases = drm_test_connector_helper_tv_get_modes_tests, +}; + +kunit_test_suite(drm_test_connector_helper_tv_get_modes_suite); + +MODULE_AUTHOR("Maxime Ripard "); +MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h index 5880daa14624..4977e0ab72db 100644 --- a/include/drm/drm_probe_helper.h +++ b/include/drm/drm_probe_helper.h @@ -35,5 +35,6 @@ int drm_connector_helper_get_modes_from_ddc(struct drm_connector *connector); int drm_connector_helper_get_modes_fixed(struct drm_connector *connector, const struct drm_display_mode *fixed_mode); int drm_connector_helper_get_modes(struct drm_connector *connector); +int drm_connector_helper_tv_get_modes(struct drm_connector *connector); #endif -- cgit v1.2.3 From 00e77a697df29cadfbb78d4b14c357b07f3bb221 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Nov 2022 10:28:56 +0100 Subject: drm/atomic-helper: Add a TV properties reset helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The drm_tv_create_properties() function will create a bunch of properties, but it's up to each and every driver using that function to properly reset the state of these properties leading to inconsistent behaviours. Let's create a helper that will take care of it. Reviewed-by: Noralf Trønnes Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-13-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_state_helper.c | 75 +++++++++++++++++++++++++++++++ include/drm/drm_atomic_state_helper.h | 1 + 2 files changed, 76 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index dfb57217253b..e1fc3f26340a 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -481,6 +481,81 @@ void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connecto } EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset); +/** + * drm_atomic_helper_connector_tv_reset - Resets Analog TV connector properties + * @connector: DRM connector + * + * Resets the analog TV properties attached to a connector + */ +void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector) +{ + struct drm_device *dev = connector->dev; + struct drm_cmdline_mode *cmdline = &connector->cmdline_mode; + struct drm_connector_state *state = connector->state; + struct drm_property *prop; + uint64_t val; + + prop = dev->mode_config.tv_mode_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.mode = val; + + if (cmdline->tv_mode_specified) + state->tv.mode = cmdline->tv_mode; + + prop = dev->mode_config.tv_select_subconnector_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.select_subconnector = val; + + prop = dev->mode_config.tv_subconnector_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.subconnector = val; + + prop = dev->mode_config.tv_brightness_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.brightness = val; + + prop = dev->mode_config.tv_contrast_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.contrast = val; + + prop = dev->mode_config.tv_flicker_reduction_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.flicker_reduction = val; + + prop = dev->mode_config.tv_overscan_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.overscan = val; + + prop = dev->mode_config.tv_saturation_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.saturation = val; + + prop = dev->mode_config.tv_hue_property; + if (prop) + if (!drm_object_property_get_default_value(&connector->base, + prop, &val)) + state->tv.hue = val; + + drm_atomic_helper_connector_tv_margins_reset(connector); +} +EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset); + /** * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state * @connector: connector object diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index 192766656b88..c8fbce795ee7 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -70,6 +70,7 @@ void __drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_ void __drm_atomic_helper_connector_reset(struct drm_connector *connector, struct drm_connector_state *conn_state); void drm_atomic_helper_connector_reset(struct drm_connector *connector); +void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector); void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector); void __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, -- cgit v1.2.3 From 5a28cefda3a94afc7761abbf4cb6270deeef8105 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 17 Nov 2022 10:28:57 +0100 Subject: drm/atomic-helper: Add an analog TV atomic_check implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The analog TV connector drivers share some atomic_check logic, and the new TV standard property have created some boilerplate that can be shared across drivers too. Let's create an atomic_check helper for those use cases. Reviewed-by: Noralf Trønnes Tested-by: Mateusz Kwiatkowski Acked-in-principle-or-something-like-that-by: Daniel Vetter Link: https://lore.kernel.org/r/20220728-rpi-analog-tv-properties-v10-14-256dad125326@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_atomic_state_helper.c | 49 +++++++++++++++++++++++++++++++ include/drm/drm_atomic_state_helper.h | 3 ++ 2 files changed, 52 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index e1fc3f26340a..22251c5f6a8a 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -556,6 +556,55 @@ void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector) } EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset); +/** + * @drm_atomic_helper_connector_tv_check: Validate an analog TV connector state + * @connector: DRM Connector + * @state: the DRM State object + * + * Checks the state object to see if the requested state is valid for an + * analog TV connector. + * + * Returns: + * Zero for success, a negative error code on error. + */ +int drm_atomic_helper_connector_tv_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct drm_connector_state *old_conn_state = + drm_atomic_get_old_connector_state(state, connector); + struct drm_connector_state *new_conn_state = + drm_atomic_get_new_connector_state(state, connector); + struct drm_crtc_state *crtc_state; + struct drm_crtc *crtc; + + crtc = new_conn_state->crtc; + if (!crtc) + return 0; + + crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + if (!crtc_state) + return -EINVAL; + + if (old_conn_state->tv.mode != new_conn_state->tv.mode) + crtc_state->mode_changed = true; + + if (old_conn_state->tv.margins.left != new_conn_state->tv.margins.left || + old_conn_state->tv.margins.right != new_conn_state->tv.margins.right || + old_conn_state->tv.margins.top != new_conn_state->tv.margins.top || + old_conn_state->tv.margins.bottom != new_conn_state->tv.margins.bottom || + old_conn_state->tv.mode != new_conn_state->tv.mode || + old_conn_state->tv.brightness != new_conn_state->tv.brightness || + old_conn_state->tv.contrast != new_conn_state->tv.contrast || + old_conn_state->tv.flicker_reduction != new_conn_state->tv.flicker_reduction || + old_conn_state->tv.overscan != new_conn_state->tv.overscan || + old_conn_state->tv.saturation != new_conn_state->tv.saturation || + old_conn_state->tv.hue != new_conn_state->tv.hue) + crtc_state->connectors_changed = true; + + return 0; +} +EXPORT_SYMBOL(drm_atomic_helper_connector_tv_check); + /** * __drm_atomic_helper_connector_duplicate_state - copy atomic connector state * @connector: connector object diff --git a/include/drm/drm_atomic_state_helper.h b/include/drm/drm_atomic_state_helper.h index c8fbce795ee7..b9740edb2658 100644 --- a/include/drm/drm_atomic_state_helper.h +++ b/include/drm/drm_atomic_state_helper.h @@ -26,6 +26,7 @@ #include +struct drm_atomic_state; struct drm_bridge; struct drm_bridge_state; struct drm_crtc; @@ -71,6 +72,8 @@ void __drm_atomic_helper_connector_reset(struct drm_connector *connector, struct drm_connector_state *conn_state); void drm_atomic_helper_connector_reset(struct drm_connector *connector); void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector); +int drm_atomic_helper_connector_tv_check(struct drm_connector *connector, + struct drm_atomic_state *state); void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector); void __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, -- cgit v1.2.3 From 2081bd8994362785b07b435bdc0c5b53d46b1205 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 23 Nov 2022 16:25:51 +0100 Subject: drm/atomic: Constify the old/new state accessors The drm_atomic_get_(old|new)_*_state don't modify the passed drm_atomic_state, so we can make it const. Reviewed-by: Javier Martinez Canillas Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20221123-rpi-kunit-tests-v1-9-051a0bb60a16@cerno.tech --- drivers/gpu/drm/drm_atomic.c | 12 ++++++------ include/drm/drm_atomic.h | 32 ++++++++++++++++---------------- 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index f197f59f6d99..e666799a46d5 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -880,7 +880,7 @@ EXPORT_SYMBOL(drm_atomic_get_private_obj_state); * or NULL if the private_obj is not part of the global atomic state. */ struct drm_private_state * -drm_atomic_get_old_private_obj_state(struct drm_atomic_state *state, +drm_atomic_get_old_private_obj_state(const struct drm_atomic_state *state, struct drm_private_obj *obj) { int i; @@ -902,7 +902,7 @@ EXPORT_SYMBOL(drm_atomic_get_old_private_obj_state); * or NULL if the private_obj is not part of the global atomic state. */ struct drm_private_state * -drm_atomic_get_new_private_obj_state(struct drm_atomic_state *state, +drm_atomic_get_new_private_obj_state(const struct drm_atomic_state *state, struct drm_private_obj *obj) { int i; @@ -934,7 +934,7 @@ EXPORT_SYMBOL(drm_atomic_get_new_private_obj_state); * not connected. */ struct drm_connector * -drm_atomic_get_old_connector_for_encoder(struct drm_atomic_state *state, +drm_atomic_get_old_connector_for_encoder(const struct drm_atomic_state *state, struct drm_encoder *encoder) { struct drm_connector_state *conn_state; @@ -968,7 +968,7 @@ EXPORT_SYMBOL(drm_atomic_get_old_connector_for_encoder); * not connected. */ struct drm_connector * -drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state, +drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state *state, struct drm_encoder *encoder) { struct drm_connector_state *conn_state; @@ -1117,7 +1117,7 @@ EXPORT_SYMBOL(drm_atomic_get_bridge_state); * the bridge is not part of the global atomic state. */ struct drm_bridge_state * -drm_atomic_get_old_bridge_state(struct drm_atomic_state *state, +drm_atomic_get_old_bridge_state(const struct drm_atomic_state *state, struct drm_bridge *bridge) { struct drm_private_state *obj_state; @@ -1139,7 +1139,7 @@ EXPORT_SYMBOL(drm_atomic_get_old_bridge_state); * the bridge is not part of the global atomic state. */ struct drm_bridge_state * -drm_atomic_get_new_bridge_state(struct drm_atomic_state *state, +drm_atomic_get_new_bridge_state(const struct drm_atomic_state *state, struct drm_bridge *bridge) { struct drm_private_state *obj_state; diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 10b1990bc1f6..92586ab55ef5 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -515,17 +515,17 @@ struct drm_private_state * __must_check drm_atomic_get_private_obj_state(struct drm_atomic_state *state, struct drm_private_obj *obj); struct drm_private_state * -drm_atomic_get_old_private_obj_state(struct drm_atomic_state *state, +drm_atomic_get_old_private_obj_state(const struct drm_atomic_state *state, struct drm_private_obj *obj); struct drm_private_state * -drm_atomic_get_new_private_obj_state(struct drm_atomic_state *state, +drm_atomic_get_new_private_obj_state(const struct drm_atomic_state *state, struct drm_private_obj *obj); struct drm_connector * -drm_atomic_get_old_connector_for_encoder(struct drm_atomic_state *state, +drm_atomic_get_old_connector_for_encoder(const struct drm_atomic_state *state, struct drm_encoder *encoder); struct drm_connector * -drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state, +drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state *state, struct drm_encoder *encoder); /** @@ -540,7 +540,7 @@ drm_atomic_get_new_connector_for_encoder(struct drm_atomic_state *state, * @drm_atomic_get_new_crtc_state should be used instead. */ static inline struct drm_crtc_state * -drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state, +drm_atomic_get_existing_crtc_state(const struct drm_atomic_state *state, struct drm_crtc *crtc) { return state->crtcs[drm_crtc_index(crtc)].state; @@ -555,7 +555,7 @@ drm_atomic_get_existing_crtc_state(struct drm_atomic_state *state, * NULL if the CRTC is not part of the global atomic state. */ static inline struct drm_crtc_state * -drm_atomic_get_old_crtc_state(struct drm_atomic_state *state, +drm_atomic_get_old_crtc_state(const struct drm_atomic_state *state, struct drm_crtc *crtc) { return state->crtcs[drm_crtc_index(crtc)].old_state; @@ -569,7 +569,7 @@ drm_atomic_get_old_crtc_state(struct drm_atomic_state *state, * NULL if the CRTC is not part of the global atomic state. */ static inline struct drm_crtc_state * -drm_atomic_get_new_crtc_state(struct drm_atomic_state *state, +drm_atomic_get_new_crtc_state(const struct drm_atomic_state *state, struct drm_crtc *crtc) { return state->crtcs[drm_crtc_index(crtc)].new_state; @@ -587,7 +587,7 @@ drm_atomic_get_new_crtc_state(struct drm_atomic_state *state, * @drm_atomic_get_new_plane_state should be used instead. */ static inline struct drm_plane_state * -drm_atomic_get_existing_plane_state(struct drm_atomic_state *state, +drm_atomic_get_existing_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane) { return state->planes[drm_plane_index(plane)].state; @@ -602,7 +602,7 @@ drm_atomic_get_existing_plane_state(struct drm_atomic_state *state, * NULL if the plane is not part of the global atomic state. */ static inline struct drm_plane_state * -drm_atomic_get_old_plane_state(struct drm_atomic_state *state, +drm_atomic_get_old_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane) { return state->planes[drm_plane_index(plane)].old_state; @@ -617,7 +617,7 @@ drm_atomic_get_old_plane_state(struct drm_atomic_state *state, * NULL if the plane is not part of the global atomic state. */ static inline struct drm_plane_state * -drm_atomic_get_new_plane_state(struct drm_atomic_state *state, +drm_atomic_get_new_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane) { return state->planes[drm_plane_index(plane)].new_state; @@ -635,7 +635,7 @@ drm_atomic_get_new_plane_state(struct drm_atomic_state *state, * @drm_atomic_get_new_connector_state should be used instead. */ static inline struct drm_connector_state * -drm_atomic_get_existing_connector_state(struct drm_atomic_state *state, +drm_atomic_get_existing_connector_state(const struct drm_atomic_state *state, struct drm_connector *connector) { int index = drm_connector_index(connector); @@ -655,7 +655,7 @@ drm_atomic_get_existing_connector_state(struct drm_atomic_state *state, * or NULL if the connector is not part of the global atomic state. */ static inline struct drm_connector_state * -drm_atomic_get_old_connector_state(struct drm_atomic_state *state, +drm_atomic_get_old_connector_state(const struct drm_atomic_state *state, struct drm_connector *connector) { int index = drm_connector_index(connector); @@ -675,7 +675,7 @@ drm_atomic_get_old_connector_state(struct drm_atomic_state *state, * or NULL if the connector is not part of the global atomic state. */ static inline struct drm_connector_state * -drm_atomic_get_new_connector_state(struct drm_atomic_state *state, +drm_atomic_get_new_connector_state(const struct drm_atomic_state *state, struct drm_connector *connector) { int index = drm_connector_index(connector); @@ -713,7 +713,7 @@ drm_atomic_get_new_connector_state(struct drm_atomic_state *state, * Read-only pointer to the current plane state. */ static inline const struct drm_plane_state * -__drm_atomic_get_current_plane_state(struct drm_atomic_state *state, +__drm_atomic_get_current_plane_state(const struct drm_atomic_state *state, struct drm_plane *plane) { if (state->planes[drm_plane_index(plane)].state) @@ -1134,10 +1134,10 @@ struct drm_bridge_state * drm_atomic_get_bridge_state(struct drm_atomic_state *state, struct drm_bridge *bridge); struct drm_bridge_state * -drm_atomic_get_old_bridge_state(struct drm_atomic_state *state, +drm_atomic_get_old_bridge_state(const struct drm_atomic_state *state, struct drm_bridge *bridge); struct drm_bridge_state * -drm_atomic_get_new_bridge_state(struct drm_atomic_state *state, +drm_atomic_get_new_bridge_state(const struct drm_atomic_state *state, struct drm_bridge *bridge); #endif /* DRM_ATOMIC_H_ */ -- cgit v1.2.3 From 11ffff9284261235cac7c9a0956943e017fe1a9f Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 23 Nov 2022 15:09:32 +0200 Subject: drm/audio: make drm_audio_component.h self-contained MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The file uses bool and struct completion, include the relevant headers. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20221123130932.3863985-1-jani.nikula@intel.com --- include/drm/drm_audio_component.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include') diff --git a/include/drm/drm_audio_component.h b/include/drm/drm_audio_component.h index 0d36bfd1a4cd..5a4cd1fa8e2a 100644 --- a/include/drm/drm_audio_component.h +++ b/include/drm/drm_audio_component.h @@ -4,6 +4,9 @@ #ifndef _DRM_AUDIO_COMPONENT_H_ #define _DRM_AUDIO_COMPONENT_H_ +#include +#include + struct drm_audio_component; struct device; -- cgit v1.2.3 From a0af74f30bb62143593c6f895ed439059d19675e Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Thu, 1 Dec 2022 09:42:46 +0100 Subject: media: uapi: add MEDIA_BUS_FMT_RGB565_1X24_CPADHI Add the MEDIA_BUS_FMT_RGB565_1X24_CPADHI format used by the Geekworm MZP280 panel for the Raspberry Pi. Signed-off-by: Chris Morgan Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20221013-rpi-dpi-improvements-v3-1-eb76e26a772d@cerno.tech Signed-off-by: Maxime Ripard --- .../userspace-api/media/v4l/subdev-formats.rst | 37 ++++++++++++++++++++++ include/uapi/linux/media-bus-format.h | 3 +- 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst index d21d532eee15..aa549c42e798 100644 --- a/Documentation/userspace-api/media/v4l/subdev-formats.rst +++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst @@ -1023,6 +1023,43 @@ The following tables list existing packed RGB formats. - b\ :sub:`2` - b\ :sub:`1` - b\ :sub:`0` + * .. _MEDIA-BUS-FMT-RGB565-1X24_CPADHI: + + - MEDIA_BUS_FMT_RGB565_1X24_CPADHI + - 0x1022 + - + - + - + - + - + - + - + - + - + - 0 + - 0 + - 0 + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` + - 0 + - 0 + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - 0 + - 0 + - 0 + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` * .. _MEDIA-BUS-FMT-BGR888-1X24: - MEDIA_BUS_FMT_BGR888_1X24 diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h index ec3323dbb927..8e159e6b4d21 100644 --- a/include/uapi/linux/media-bus-format.h +++ b/include/uapi/linux/media-bus-format.h @@ -34,7 +34,7 @@ #define MEDIA_BUS_FMT_FIXED 0x0001 -/* RGB - next is 0x1022 */ +/* RGB - next is 0x1023 */ #define MEDIA_BUS_FMT_RGB444_1X12 0x1016 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002 @@ -48,6 +48,7 @@ #define MEDIA_BUS_FMT_RGB666_1X18 0x1009 #define MEDIA_BUS_FMT_RBG888_1X24 0x100e #define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015 +#define MEDIA_BUS_FMT_RGB565_1X24_CPADHI 0x1022 #define MEDIA_BUS_FMT_RGB666_1X7X3_SPWG 0x1010 #define MEDIA_BUS_FMT_BGR888_1X24 0x1013 #define MEDIA_BUS_FMT_BGR888_3X8 0x101b -- cgit v1.2.3 From 2468e0195c09706896712a29030132e7f1bd0bcc Mon Sep 17 00:00:00 2001 From: Joerg Quinten Date: Thu, 1 Dec 2022 09:42:47 +0100 Subject: media: uapi: add MEDIA_BUS_FMT_BGR666_1X18 Add the BGR666 format MEDIA_BUS_FMT_BGR666_1X18 supported by the RaspberryPi. Signed-off-by: Joerg Quinten Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20221013-rpi-dpi-improvements-v3-2-eb76e26a772d@cerno.tech Signed-off-by: Maxime Ripard --- .../userspace-api/media/v4l/subdev-formats.rst | 37 ++++++++++++++++++++++ include/uapi/linux/media-bus-format.h | 3 +- 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst index aa549c42e798..6605c056cc7c 100644 --- a/Documentation/userspace-api/media/v4l/subdev-formats.rst +++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst @@ -949,6 +949,43 @@ The following tables list existing packed RGB formats. - b\ :sub:`2` - b\ :sub:`1` - b\ :sub:`0` + * .. _MEDIA-BUS-FMT-BGR666-1X18: + + - MEDIA_BUS_FMT_BGR666_1X18 + - 0x1023 + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` * .. _MEDIA-BUS-FMT-RBG888-1X24: - MEDIA_BUS_FMT_RBG888_1X24 diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h index 8e159e6b4d21..6ce56a984112 100644 --- a/include/uapi/linux/media-bus-format.h +++ b/include/uapi/linux/media-bus-format.h @@ -34,7 +34,7 @@ #define MEDIA_BUS_FMT_FIXED 0x0001 -/* RGB - next is 0x1023 */ +/* RGB - next is 0x1024 */ #define MEDIA_BUS_FMT_RGB444_1X12 0x1016 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002 @@ -46,6 +46,7 @@ #define MEDIA_BUS_FMT_RGB565_2X8_BE 0x1007 #define MEDIA_BUS_FMT_RGB565_2X8_LE 0x1008 #define MEDIA_BUS_FMT_RGB666_1X18 0x1009 +#define MEDIA_BUS_FMT_BGR666_1X18 0x1023 #define MEDIA_BUS_FMT_RBG888_1X24 0x100e #define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015 #define MEDIA_BUS_FMT_RGB565_1X24_CPADHI 0x1022 -- cgit v1.2.3 From 1113f644c488225212eebd3966360326579e2d3d Mon Sep 17 00:00:00 2001 From: Joerg Quinten Date: Thu, 1 Dec 2022 09:42:48 +0100 Subject: media: uapi: add MEDIA_BUS_FMT_BGR666_1X24_CPADHI Add the BGR666 format MEDIA_BUS_FMT_BGR666_1X24_CPADHI supported by the RaspberryPi. Signed-off-by: Joerg Quinten Reviewed-by: Laurent Pinchart Link: https://lore.kernel.org/r/20221013-rpi-dpi-improvements-v3-3-eb76e26a772d@cerno.tech Signed-off-by: Maxime Ripard --- .../userspace-api/media/v4l/subdev-formats.rst | 37 ++++++++++++++++++++++ include/uapi/linux/media-bus-format.h | 3 +- 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst index 6605c056cc7c..5f2ce6eada71 100644 --- a/Documentation/userspace-api/media/v4l/subdev-formats.rst +++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst @@ -1060,6 +1060,43 @@ The following tables list existing packed RGB formats. - b\ :sub:`2` - b\ :sub:`1` - b\ :sub:`0` + * .. _MEDIA-BUS-FMT-BGR666-1X24_CPADHI: + + - MEDIA_BUS_FMT_BGR666_1X24_CPADHI + - 0x1024 + - + - + - + - + - + - + - + - + - + - 0 + - 0 + - b\ :sub:`5` + - b\ :sub:`4` + - b\ :sub:`3` + - b\ :sub:`2` + - b\ :sub:`1` + - b\ :sub:`0` + - 0 + - 0 + - g\ :sub:`5` + - g\ :sub:`4` + - g\ :sub:`3` + - g\ :sub:`2` + - g\ :sub:`1` + - g\ :sub:`0` + - 0 + - 0 + - r\ :sub:`5` + - r\ :sub:`4` + - r\ :sub:`3` + - r\ :sub:`2` + - r\ :sub:`1` + - r\ :sub:`0` * .. _MEDIA-BUS-FMT-RGB565-1X24_CPADHI: - MEDIA_BUS_FMT_RGB565_1X24_CPADHI diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h index 6ce56a984112..f3b0b8091a2c 100644 --- a/include/uapi/linux/media-bus-format.h +++ b/include/uapi/linux/media-bus-format.h @@ -34,7 +34,7 @@ #define MEDIA_BUS_FMT_FIXED 0x0001 -/* RGB - next is 0x1024 */ +/* RGB - next is 0x1025 */ #define MEDIA_BUS_FMT_RGB444_1X12 0x1016 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001 #define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002 @@ -49,6 +49,7 @@ #define MEDIA_BUS_FMT_BGR666_1X18 0x1023 #define MEDIA_BUS_FMT_RBG888_1X24 0x100e #define MEDIA_BUS_FMT_RGB666_1X24_CPADHI 0x1015 +#define MEDIA_BUS_FMT_BGR666_1X24_CPADHI 0x1024 #define MEDIA_BUS_FMT_RGB565_1X24_CPADHI 0x1022 #define MEDIA_BUS_FMT_RGB666_1X7X3_SPWG 0x1010 #define MEDIA_BUS_FMT_BGR888_1X24 0x1013 -- cgit v1.2.3 From 00b5497d642bec3ceef85f3abe642d991a75ddf0 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 2 Dec 2022 13:56:37 +0100 Subject: drm/simple-kms: Remove drm_gem_simple_display_pipe_prepare_fb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The helper drm_gem_simple_display_pipe_prepare_fb() is simple-KMS' default implementation for prepare_fb. Remove the call from drivers that set it explicitly. Then inline the helper into the only caller within simple-kms helpers. No functional changes. Simple-KMS drivers that implement the prepare_fb callback should call drm_gem_plane_helper_prepare_fb() directly. v2: * fix typo in commit message Signed-off-by: Thomas Zimmermann Reviewed-by: Noralf Trønnes Link: https://patchwork.freedesktop.org/patch/msgid/20221202125644.7917-2-tzimmermann@suse.de --- drivers/gpu/drm/drm_gem_atomic_helper.c | 31 +--------------------------- drivers/gpu/drm/drm_simple_kms_helper.c | 2 +- drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 1 - drivers/gpu/drm/tiny/ili9163.c | 1 - include/drm/drm_gem_atomic_helper.h | 2 -- include/drm/drm_plane.h | 4 ++-- include/drm/drm_simple_kms_helper.h | 4 ++-- 7 files changed, 6 insertions(+), 39 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c index e42800718f51..5d4b9cd077f7 100644 --- a/drivers/gpu/drm/drm_gem_atomic_helper.c +++ b/drivers/gpu/drm/drm_gem_atomic_helper.c @@ -26,11 +26,8 @@ * call drm_gem_plane_helper_prepare_fb() from their implementation of * struct &drm_plane_helper.prepare_fb . It sets the plane's fence from * the framebuffer so that the DRM core can synchronize access automatically. - * * drm_gem_plane_helper_prepare_fb() can also be used directly as - * implementation of prepare_fb. For drivers based on - * struct drm_simple_display_pipe, drm_gem_simple_display_pipe_prepare_fb() - * provides equivalent functionality. + * implementation of prepare_fb. * * .. code-block:: c * @@ -41,11 +38,6 @@ * . prepare_fb = drm_gem_plane_helper_prepare_fb, * }; * - * struct drm_simple_display_pipe_funcs driver_pipe_funcs = { - * ..., - * . prepare_fb = drm_gem_simple_display_pipe_prepare_fb, - * }; - * * A driver using a shadow buffer copies the content of the shadow buffers * into the HW's framebuffer memory during an atomic update. This requires * a mapping of the shadow buffer into kernel address space. The mappings @@ -205,27 +197,6 @@ error: } EXPORT_SYMBOL_GPL(drm_gem_plane_helper_prepare_fb); -/** - * drm_gem_simple_display_pipe_prepare_fb - prepare_fb helper for &drm_simple_display_pipe - * @pipe: Simple display pipe - * @plane_state: Plane state - * - * This function uses drm_gem_plane_helper_prepare_fb() to extract the fences - * from &drm_gem_object.resv and attaches them to the plane state for the atomic - * helper to wait on. This is necessary to correctly implement implicit - * synchronization for any buffers shared as a struct &dma_buf. Drivers can use - * this as their &drm_simple_display_pipe_funcs.prepare_fb callback. - * - * See drm_gem_plane_helper_prepare_fb() for a discussion of implicit and - * explicit fencing in atomic modeset updates. - */ -int drm_gem_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state) -{ - return drm_gem_plane_helper_prepare_fb(&pipe->plane, plane_state); -} -EXPORT_SYMBOL(drm_gem_simple_display_pipe_prepare_fb); - /* * Shadow-buffered Planes */ diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 3ef420ec4534..270523ae36d4 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -267,7 +267,7 @@ static int drm_simple_kms_plane_prepare_fb(struct drm_plane *plane, WARN_ON_ONCE(pipe->funcs && pipe->funcs->cleanup_fb); - return drm_gem_simple_display_pipe_prepare_fb(pipe, state); + return drm_gem_plane_helper_prepare_fb(plane, state); } return pipe->funcs->prepare_fb(pipe, state); diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index 384a724f2822..be088983aa7c 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -581,7 +581,6 @@ static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = { .enable = ili9341_dbi_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, - .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, }; static const struct drm_display_mode ili9341_dbi_mode = { diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index ca0451f79962..835ed12792d5 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -104,7 +104,6 @@ static const struct drm_simple_display_pipe_funcs ili9163_pipe_funcs = { .enable = yx240qv29_enable, .disable = mipi_dbi_pipe_disable, .update = mipi_dbi_pipe_update, - .prepare_fb = drm_gem_simple_display_pipe_prepare_fb, }; static const struct drm_display_mode yx240qv29_mode = { diff --git a/include/drm/drm_gem_atomic_helper.h b/include/drm/drm_gem_atomic_helper.h index 6970ccb787e2..40b8b039518e 100644 --- a/include/drm/drm_gem_atomic_helper.h +++ b/include/drm/drm_gem_atomic_helper.h @@ -15,8 +15,6 @@ struct drm_simple_display_pipe; */ int drm_gem_plane_helper_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state); -int drm_gem_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pipe, - struct drm_plane_state *plane_state); /* * Helpers for planes with shadow buffers diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 447e664e49d5..51291983ea44 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -77,8 +77,8 @@ struct drm_plane_state { * write this field directly for a driver's implicit fence. * * Drivers should store any implicit fence in this from their - * &drm_plane_helper_funcs.prepare_fb callback. See drm_gem_plane_helper_prepare_fb() - * and drm_gem_simple_display_pipe_prepare_fb() for suitable helpers. + * &drm_plane_helper_funcs.prepare_fb callback. See + * drm_gem_plane_helper_prepare_fb() for a suitable helper. */ struct dma_fence *fence; diff --git a/include/drm/drm_simple_kms_helper.h b/include/drm/drm_simple_kms_helper.h index 2298fe3af4cd..b2486d073763 100644 --- a/include/drm/drm_simple_kms_helper.h +++ b/include/drm/drm_simple_kms_helper.h @@ -117,9 +117,9 @@ struct drm_simple_display_pipe_funcs { * more details. * * For GEM drivers who neither have a @prepare_fb nor @cleanup_fb hook - * set drm_gem_simple_display_pipe_prepare_fb() is called automatically + * set, drm_gem_plane_helper_prepare_fb() is called automatically * to implement this. Other drivers which need additional plane - * processing can call drm_gem_simple_display_pipe_prepare_fb() from + * processing can call drm_gem_plane_helper_prepare_fb() from * their @prepare_fb hook. */ int (*prepare_fb)(struct drm_simple_display_pipe *pipe, -- cgit v1.2.3 From 63aa5ec6cf2f332ec4ef08a03f4f39895f82b2b9 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 2 Dec 2022 13:56:40 +0100 Subject: drm/mipi-dbi: Initialize default driver functions with macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS to initialize MIPI-DBI helpers to default values and convert drivers. The prepare_fb function set by some drivers is called implicitly by simple-kms helpers, so leave it out. Signed-off-by: Thomas Zimmermann Reviewed-by: Noralf Trønnes Tested-by: Javier Martinez Canillas Tested-by: Noralf Trønnes # drm/tiny/mi0283qt Link: https://patchwork.freedesktop.org/patch/msgid/20221202125644.7917-5-tzimmermann@suse.de --- drivers/gpu/drm/panel/panel-ilitek-ili9341.c | 5 +---- drivers/gpu/drm/tiny/hx8357d.c | 5 +---- drivers/gpu/drm/tiny/ili9163.c | 5 +---- drivers/gpu/drm/tiny/ili9341.c | 5 +---- drivers/gpu/drm/tiny/ili9486.c | 5 +---- drivers/gpu/drm/tiny/mi0283qt.c | 5 +---- drivers/gpu/drm/tiny/panel-mipi-dbi.c | 5 +---- drivers/gpu/drm/tiny/st7735r.c | 5 +---- include/drm/drm_mipi_dbi.h | 16 ++++++++++++++++ 9 files changed, 24 insertions(+), 32 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c index be088983aa7c..3fdf884b3257 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c @@ -577,10 +577,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs ili9341_dbi_funcs = { - .mode_valid = mipi_dbi_pipe_mode_valid, - .enable = ili9341_dbi_enable, - .disable = mipi_dbi_pipe_disable, - .update = mipi_dbi_pipe_update, + DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(ili9341_dbi_enable), }; static const struct drm_display_mode ili9341_dbi_mode = { diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index 9f634f720817..cdc4486e059b 100644 --- a/drivers/gpu/drm/tiny/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -181,10 +181,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs hx8357d_pipe_funcs = { - .mode_valid = mipi_dbi_pipe_mode_valid, - .enable = yx240qv29_enable, - .disable = mipi_dbi_pipe_disable, - .update = mipi_dbi_pipe_update, + DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable), }; static const struct drm_display_mode yx350hv15_mode = { diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c index 835ed12792d5..bc4384d410fc 100644 --- a/drivers/gpu/drm/tiny/ili9163.c +++ b/drivers/gpu/drm/tiny/ili9163.c @@ -100,10 +100,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs ili9163_pipe_funcs = { - .mode_valid = mipi_dbi_pipe_mode_valid, - .enable = yx240qv29_enable, - .disable = mipi_dbi_pipe_disable, - .update = mipi_dbi_pipe_update, + DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable), }; static const struct drm_display_mode yx240qv29_mode = { diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index 420f6005a956..47b61c3bf145 100644 --- a/drivers/gpu/drm/tiny/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -137,10 +137,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs ili9341_pipe_funcs = { - .mode_valid = mipi_dbi_pipe_mode_valid, - .enable = yx240qv29_enable, - .disable = mipi_dbi_pipe_disable, - .update = mipi_dbi_pipe_update, + DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(yx240qv29_enable), }; static const struct drm_display_mode yx240qv29_mode = { diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c index 1bb847466b10..9f735d84d85d 100644 --- a/drivers/gpu/drm/tiny/ili9486.c +++ b/drivers/gpu/drm/tiny/ili9486.c @@ -150,10 +150,7 @@ static void waveshare_enable(struct drm_simple_display_pipe *pipe, } static const struct drm_simple_display_pipe_funcs waveshare_pipe_funcs = { - .mode_valid = mipi_dbi_pipe_mode_valid, - .enable = waveshare_enable, - .disable = mipi_dbi_pipe_disable, - .update = mipi_dbi_pipe_update, + DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(waveshare_enable), }; static const struct drm_display_mode waveshare_mode = { diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index 47df2b5a3048..01ff43c8ac3f 100644 --- a/drivers/gpu/drm/tiny/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -141,10 +141,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs mi0283qt_pipe_funcs = { - .mode_valid = mipi_dbi_pipe_mode_valid, - .enable = mi0283qt_enable, - .disable = mipi_dbi_pipe_disable, - .update = mipi_dbi_pipe_update, + DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(mi0283qt_enable), }; static const struct drm_display_mode mi0283qt_mode = { diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c index 03a7d569cd56..2ed23ded5199 100644 --- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c +++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c @@ -212,10 +212,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs panel_mipi_dbi_pipe_funcs = { - .mode_valid = mipi_dbi_pipe_mode_valid, - .enable = panel_mipi_dbi_enable, - .disable = mipi_dbi_pipe_disable, - .update = mipi_dbi_pipe_update, + DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(panel_mipi_dbi_enable), }; DEFINE_DRM_GEM_DMA_FOPS(panel_mipi_dbi_fops); diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index 15d9cf283c66..477eb36fbb70 100644 --- a/drivers/gpu/drm/tiny/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -133,10 +133,7 @@ out_exit: } static const struct drm_simple_display_pipe_funcs st7735r_pipe_funcs = { - .mode_valid = mipi_dbi_pipe_mode_valid, - .enable = st7735r_pipe_enable, - .disable = mipi_dbi_pipe_disable, - .update = mipi_dbi_pipe_update, + DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(st7735r_pipe_enable), }; static const struct st7735r_cfg jd_t18003_t01_cfg = { diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h index 14eaecb1825c..8c4ea7956d61 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -207,4 +207,20 @@ void mipi_dbi_debugfs_init(struct drm_minor *minor); static inline void mipi_dbi_debugfs_init(struct drm_minor *minor) {} #endif +/** + * DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS - Initializes struct drm_simple_display_pipe_funcs + * for MIPI-DBI devices + * @enable_: Enable-callback implementation + * + * This macro initializes struct drm_simple_display_pipe_funcs with default + * values for MIPI-DBI-based devices. The only callback that depends on the + * hardware is @enable, for which the driver has to provide an implementation. + * MIPI-based drivers are encouraged to use this macro for initialization. + */ +#define DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(enable_) \ + .mode_valid = mipi_dbi_pipe_mode_valid, \ + .enable = (enable_), \ + .disable = mipi_dbi_pipe_disable, \ + .update = mipi_dbi_pipe_update + #endif /* __LINUX_MIPI_DBI_H */ -- cgit v1.2.3 From b5f636e63b807fdeba5d61260e5f6b24f6834f69 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 2 Dec 2022 13:56:41 +0100 Subject: drm/mipi-dbi: Prepare framebuffer copy operation in pipe-update helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the vmap/vunmap blocks from the inner fb_dirty helpers into the MIPI DBI update helpers. The function calls can result in waiting and/or processing overhead. Reduce the penalties by executing the functions once in the outer-most function of the pipe update. This change also prepares for MIPI DBI for shadow-plane helpers. With shadow-plane helpers, transfer source buffers are mapped into kernel address space automatically. v2: * keep each driver's existing buffer-mapping patter (Noralf) * zero-initialize iosys_map arrays (Noralf) Signed-off-by: Thomas Zimmermann Reviewed-by: Noralf Trønnes Tested-by: Javier Martinez Canillas Tested-by: Noralf Trønnes # drm/tiny/mi0283qt Link: https://patchwork.freedesktop.org/patch/msgid/20221202125644.7917-6-tzimmermann@suse.de --- drivers/gpu/drm/drm_mipi_dbi.c | 63 ++++++++++++++++++++++-------------------- drivers/gpu/drm/tiny/ili9225.c | 25 +++++++++++++---- drivers/gpu/drm/tiny/st7586.c | 28 +++++++++++++------ include/drm/drm_mipi_dbi.h | 6 ++-- 4 files changed, 75 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index a6ac56580876..f58123327ed6 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -192,6 +192,7 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf); /** * mipi_dbi_buf_copy - Copy a framebuffer, transforming it if necessary * @dst: The destination buffer + * @src: The source buffer * @fb: The source framebuffer * @clip: Clipping rectangle of the area to be copied * @swap: When true, swap MSB/LSB of 16-bit values @@ -199,12 +200,10 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf); * Returns: * Zero on success, negative error code on failure. */ -int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, +int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *fb, struct drm_rect *clip, bool swap) { struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); - struct iosys_map map[DRM_FORMAT_MAX_PLANES]; - struct iosys_map data[DRM_FORMAT_MAX_PLANES]; struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst); int ret; @@ -212,19 +211,15 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, if (ret) return ret; - ret = drm_gem_fb_vmap(fb, map, data); - if (ret) - goto out_drm_gem_fb_end_cpu_access; - switch (fb->format->format) { case DRM_FORMAT_RGB565: if (swap) - drm_fb_swab(&dst_map, NULL, data, fb, clip, !gem->import_attach); + drm_fb_swab(&dst_map, NULL, src, fb, clip, !gem->import_attach); else - drm_fb_memcpy(&dst_map, NULL, data, fb, clip); + drm_fb_memcpy(&dst_map, NULL, src, fb, clip); break; case DRM_FORMAT_XRGB8888: - drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, data, fb, clip, swap); + drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, src, fb, clip, swap); break; default: drm_err_once(fb->dev, "Format is not supported: %p4cc\n", @@ -232,8 +227,6 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, ret = -EINVAL; } - drm_gem_fb_vunmap(fb, map); -out_drm_gem_fb_end_cpu_access: drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); return ret; @@ -257,10 +250,9 @@ static void mipi_dbi_set_window_address(struct mipi_dbi_dev *dbidev, ys & 0xff, (ye >> 8) & 0xff, ye & 0xff); } -static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) +static void mipi_dbi_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb, + struct drm_rect *rect) { - struct iosys_map map[DRM_FORMAT_MAX_PLANES]; - struct iosys_map data[DRM_FORMAT_MAX_PLANES]; struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; @@ -270,16 +262,9 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) bool full; void *tr; - if (WARN_ON(!fb)) - return; - if (!drm_dev_enter(fb->dev, &idx)) return; - ret = drm_gem_fb_vmap(fb, map, data); - if (ret) - goto err_drm_dev_exit; - full = width == fb->width && height == fb->height; DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); @@ -287,11 +272,11 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) if (!dbi->dc || !full || swap || fb->format->format == DRM_FORMAT_XRGB8888) { tr = dbidev->tx_buf; - ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap); + ret = mipi_dbi_buf_copy(tr, src, fb, rect, swap); if (ret) goto err_msg; } else { - tr = data[0].vaddr; /* TODO: Use mapping abstraction properly */ + tr = src->vaddr; /* TODO: Use mapping abstraction properly */ } mipi_dbi_set_window_address(dbidev, rect->x1, rect->x2 - 1, rect->y1, @@ -303,9 +288,6 @@ err_msg: if (ret) drm_err_once(fb->dev, "Failed to update display %d\n", ret); - drm_gem_fb_vunmap(fb, map); - -err_drm_dev_exit: drm_dev_exit(idx); } @@ -338,14 +320,27 @@ EXPORT_SYMBOL(mipi_dbi_pipe_mode_valid); void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_state) { + struct iosys_map map[DRM_FORMAT_MAX_PLANES] = { }; + struct iosys_map data[DRM_FORMAT_MAX_PLANES] = { }; struct drm_plane_state *state = pipe->plane.state; + struct drm_framebuffer *fb = state->fb; struct drm_rect rect; + int ret; if (!pipe->crtc.state->active) return; + if (WARN_ON(!fb)) + return; + + ret = drm_gem_fb_vmap(fb, map, data); + if (ret) + return; + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) - mipi_dbi_fb_dirty(state->fb, &rect); + mipi_dbi_fb_dirty(&data[0], fb, &rect); + + drm_gem_fb_vunmap(fb, map); } EXPORT_SYMBOL(mipi_dbi_pipe_update); @@ -373,14 +368,22 @@ void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, .y1 = 0, .y2 = fb->height, }; - int idx; + struct iosys_map map[DRM_FORMAT_MAX_PLANES] = { }; + struct iosys_map data[DRM_FORMAT_MAX_PLANES] = { }; + int idx, ret; if (!drm_dev_enter(&dbidev->drm, &idx)) return; - mipi_dbi_fb_dirty(fb, &rect); + ret = drm_gem_fb_vmap(fb, map, data); + if (ret) + goto err_drm_dev_exit; + + mipi_dbi_fb_dirty(&data[0], fb, &rect); backlight_enable(dbidev->backlight); + drm_gem_fb_vunmap(fb, map); +err_drm_dev_exit: drm_dev_exit(idx); } EXPORT_SYMBOL(mipi_dbi_enable_flush); diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index f05a2d25866c..ae94c74d0163 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -76,9 +77,9 @@ static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data) return mipi_dbi_command_buf(dbi, cmd, par, 2); } -static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) +static void ili9225_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb, + struct drm_rect *rect) { - struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; @@ -100,11 +101,11 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) if (!dbi->dc || !full || swap || fb->format->format == DRM_FORMAT_XRGB8888) { tr = dbidev->tx_buf; - ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap); + ret = mipi_dbi_buf_copy(tr, src, fb, rect, swap); if (ret) goto err_msg; } else { - tr = dma_obj->vaddr; + tr = src->vaddr; /* TODO: Use mapping abstraction properly */ } switch (dbidev->rotation) { @@ -163,13 +164,19 @@ static void ili9225_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_state) { struct drm_plane_state *state = pipe->plane.state; + struct drm_framebuffer *fb = state->fb; + struct drm_gem_dma_object *dma_obj; + struct iosys_map src; struct drm_rect rect; if (!pipe->crtc.state->active) return; + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); + iosys_map_set_vaddr(&src, dma_obj->vaddr); + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) - ili9225_fb_dirty(state->fb, &rect); + ili9225_fb_dirty(&src, fb, &rect); } static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, @@ -186,6 +193,8 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, .y1 = 0, .y2 = fb->height, }; + struct drm_gem_dma_object *dma_obj; + struct iosys_map src; int ret, idx; u8 am_id; @@ -276,7 +285,11 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017); - ili9225_fb_dirty(fb, &rect); + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); + iosys_map_set_vaddr(&src, dma_obj->vaddr); + + ili9225_fb_dirty(&src, fb, &rect); + out_exit: drm_dev_exit(idx); } diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 6bdd23e2a47c..e773b1f2fd5f 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -92,25 +92,24 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, kfree(buf); } -static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, +static int st7586_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *fb, struct drm_rect *clip) { - struct drm_gem_dma_object *dma_obj = drm_fb_dma_get_gem_obj(fb, 0); - void *src = dma_obj->vaddr; - int ret = 0; + int ret; ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE); if (ret) return ret; - st7586_xrgb8888_to_gray332(dst, src, fb, clip); + st7586_xrgb8888_to_gray332(dst, src->vaddr, fb, clip); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); return 0; } -static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) +static void st7586_fb_dirty(struct iosys_map *src, struct drm_framebuffer *fb, + struct drm_rect *rect) { struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); struct mipi_dbi *dbi = &dbidev->dbi; @@ -125,7 +124,7 @@ static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); - ret = st7586_buf_copy(dbidev->tx_buf, fb, rect); + ret = st7586_buf_copy(dbidev->tx_buf, src, fb, rect); if (ret) goto err_msg; @@ -154,13 +153,19 @@ static void st7586_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_state) { struct drm_plane_state *state = pipe->plane.state; + struct drm_framebuffer *fb = state->fb; + struct drm_gem_dma_object *dma_obj; + struct iosys_map src; struct drm_rect rect; if (!pipe->crtc.state->active) return; + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); + iosys_map_set_vaddr(&src, dma_obj->vaddr); + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) - st7586_fb_dirty(state->fb, &rect); + st7586_fb_dirty(&src, fb, &rect); } static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, @@ -176,6 +181,8 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, .y1 = 0, .y2 = fb->height, }; + struct drm_gem_dma_object *dma_obj; + struct iosys_map src; int idx, ret; u8 addr_mode; @@ -235,7 +242,10 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, msleep(100); - st7586_fb_dirty(fb, &rect); + dma_obj = drm_fb_dma_get_gem_obj(fb, 0); + iosys_map_set_vaddr(&src, dma_obj->vaddr); + + st7586_fb_dirty(&src, fb, &rect); mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); out_exit: diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h index 8c4ea7956d61..36ac8495566b 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -13,9 +13,10 @@ #include struct drm_rect; -struct spi_device; struct gpio_desc; +struct iosys_map; struct regulator; +struct spi_device; /** * struct mipi_dbi - MIPI DBI interface @@ -176,8 +177,9 @@ int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val); int mipi_dbi_command_buf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len); int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, const u8 *data, size_t len); -int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, +int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *fb, struct drm_rect *clip, bool swap); + /** * mipi_dbi_command - MIPI DCS command with optional parameter(s) * @dbi: MIPI DBI structure -- cgit v1.2.3 From e7caf04d49533fb38d22379be0278a34aad8826f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Fri, 2 Dec 2022 13:56:42 +0100 Subject: drm/mipi-dbi: Support shadow-plane state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement MIPI DBI planes with struct drm_shadow_plane_state, so that the respective drivers can use the vmap'ed GEM-buffer memory. Implement state helpers, the {begin,end}_fb_access helpers and wire up everything. With this commit, MIPI DBI drivers can access the GEM object's memory that is provided by shadow-plane state. The actual changes to drivers are implemented separately. v2: * use shadow-plane state directly (Noralf) Signed-off-by: Thomas Zimmermann Reviewed-by: Noralf Trønnes Tested-by: Javier Martinez Canillas Tested-by: Noralf Trønnes # drm/tiny/mi0283qt Link: https://patchwork.freedesktop.org/patch/msgid/20221202125644.7917-7-tzimmermann@suse.de --- drivers/gpu/drm/drm_mipi_dbi.c | 85 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/tiny/ili9225.c | 5 +++ drivers/gpu/drm/tiny/st7586.c | 5 +++ include/drm/drm_mipi_dbi.h | 16 +++++++- 4 files changed, 110 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index f58123327ed6..b808de61c5bc 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -433,6 +434,90 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) } EXPORT_SYMBOL(mipi_dbi_pipe_disable); +/** + * mipi_dbi_pipe_begin_fb_access - MIPI DBI pipe begin-access helper + * @pipe: Display pipe + * @plane_state: Plane state + * + * This function implements struct &drm_simple_display_funcs.begin_fb_access. + * + * See drm_gem_begin_shadow_fb_access() for details and mipi_dbi_pipe_cleanup_fb() + * for cleanup. + * + * Returns: + * 0 on success, or a negative errno code otherwise. + */ +int mipi_dbi_pipe_begin_fb_access(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *plane_state) +{ + return drm_gem_begin_shadow_fb_access(&pipe->plane, plane_state); +} +EXPORT_SYMBOL(mipi_dbi_pipe_begin_fb_access); + +/** + * mipi_dbi_pipe_end_fb_access - MIPI DBI pipe end-access helper + * @pipe: Display pipe + * @plane_state: Plane state + * + * This function implements struct &drm_simple_display_funcs.end_fb_access. + * + * See mipi_dbi_pipe_begin_fb_access(). + */ +void mipi_dbi_pipe_end_fb_access(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *plane_state) +{ + drm_gem_end_shadow_fb_access(&pipe->plane, plane_state); +} +EXPORT_SYMBOL(mipi_dbi_pipe_end_fb_access); + +/** + * mipi_dbi_pipe_reset_plane - MIPI DBI plane-reset helper + * @pipe: Display pipe + * + * This function implements struct &drm_simple_display_funcs.reset_plane + * for MIPI DBI planes. + */ +void mipi_dbi_pipe_reset_plane(struct drm_simple_display_pipe *pipe) +{ + drm_gem_reset_shadow_plane(&pipe->plane); +} +EXPORT_SYMBOL(mipi_dbi_pipe_reset_plane); + +/** + * mipi_dbi_pipe_duplicate_plane_state - duplicates MIPI DBI plane state + * @pipe: Display pipe + * + * This function implements struct &drm_simple_display_funcs.duplicate_plane_state + * for MIPI DBI planes. + * + * See drm_gem_duplicate_shadow_plane_state() for additional details. + * + * Returns: + * A pointer to a new plane state on success, or NULL otherwise. + */ +struct drm_plane_state *mipi_dbi_pipe_duplicate_plane_state(struct drm_simple_display_pipe *pipe) +{ + return drm_gem_duplicate_shadow_plane_state(&pipe->plane); +} +EXPORT_SYMBOL(mipi_dbi_pipe_duplicate_plane_state); + +/** + * mipi_dbi_pipe_destroy_plane_state - cleans up MIPI DBI plane state + * @pipe: Display pipe + * @plane_state: Plane state + * + * This function implements struct drm_simple_display_funcs.destroy_plane_state + * for MIPI DBI planes. + * + * See drm_gem_destroy_shadow_plane_state() for additional details. + */ +void mipi_dbi_pipe_destroy_plane_state(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *plane_state) +{ + drm_gem_destroy_shadow_plane_state(&pipe->plane, plane_state); +} +EXPORT_SYMBOL(mipi_dbi_pipe_destroy_plane_state); + static int mipi_dbi_connector_get_modes(struct drm_connector *connector) { struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(connector->dev); diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index ae94c74d0163..a69aec8402bc 100644 --- a/drivers/gpu/drm/tiny/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -343,6 +343,11 @@ static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = { .enable = ili9225_pipe_enable, .disable = ili9225_pipe_disable, .update = ili9225_pipe_update, + .begin_fb_access = mipi_dbi_pipe_begin_fb_access, + .end_fb_access = mipi_dbi_pipe_end_fb_access, + .reset_plane = mipi_dbi_pipe_reset_plane, + .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state, + .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state, }; static const struct drm_display_mode ili9225_mode = { diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c index e773b1f2fd5f..76b13cefc904 100644 --- a/drivers/gpu/drm/tiny/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -277,6 +277,11 @@ static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = { .enable = st7586_pipe_enable, .disable = st7586_pipe_disable, .update = st7586_pipe_update, + .begin_fb_access = mipi_dbi_pipe_begin_fb_access, + .end_fb_access = mipi_dbi_pipe_end_fb_access, + .reset_plane = mipi_dbi_pipe_reset_plane, + .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state, + .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state, }; static const struct drm_display_mode st7586_mode = { diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h index 36ac8495566b..304fbecdc66a 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -164,6 +164,15 @@ void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, struct drm_crtc_state *crtc_state, struct drm_plane_state *plan_state); void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe); +int mipi_dbi_pipe_begin_fb_access(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *plane_state); +void mipi_dbi_pipe_end_fb_access(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *plane_state); +void mipi_dbi_pipe_reset_plane(struct drm_simple_display_pipe *pipe); +struct drm_plane_state *mipi_dbi_pipe_duplicate_plane_state(struct drm_simple_display_pipe *pipe); +void mipi_dbi_pipe_destroy_plane_state(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *plane_state); + void mipi_dbi_hw_reset(struct mipi_dbi *dbi); bool mipi_dbi_display_is_on(struct mipi_dbi *dbi); int mipi_dbi_poweron_reset(struct mipi_dbi_dev *dbidev); @@ -223,6 +232,11 @@ static inline void mipi_dbi_debugfs_init(struct drm_minor *minor) {} .mode_valid = mipi_dbi_pipe_mode_valid, \ .enable = (enable_), \ .disable = mipi_dbi_pipe_disable, \ - .update = mipi_dbi_pipe_update + .update = mipi_dbi_pipe_update, \ + .begin_fb_access = mipi_dbi_pipe_begin_fb_access, \ + .end_fb_access = mipi_dbi_pipe_end_fb_access, \ + .reset_plane = mipi_dbi_pipe_reset_plane, \ + .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state, \ + .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state #endif /* __LINUX_MIPI_DBI_H */ -- cgit v1.2.3 From cd3a8a596214e6a338a22104936c40e62bdea2b6 Mon Sep 17 00:00:00 2001 From: Christian König Date: Fri, 18 Nov 2022 20:22:21 +0100 Subject: drm/ttm: remove ttm_bo_(un)lock_delayed_workqueue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those functions never worked correctly since it is still perfectly possible that a buffer object is released and the background worker restarted even after calling them. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Reviewed-by: Arunpravin Paneer Selvam Link: https://patchwork.freedesktop.org/patch/msgid/20221125102137.1801-2-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 6 +----- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 4 +--- drivers/gpu/drm/radeon/radeon_device.c | 5 ----- drivers/gpu/drm/radeon/radeon_pm.c | 4 +--- drivers/gpu/drm/ttm/ttm_bo.c | 14 -------------- include/drm/ttm/ttm_bo_api.h | 16 ---------------- 6 files changed, 3 insertions(+), 46 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 0f16d3c09309..f60753f97ac5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1717,7 +1717,7 @@ no_preempt: static int amdgpu_debugfs_ib_preempt(void *data, u64 val) { - int r, resched, length; + int r, length; struct amdgpu_ring *ring; struct dma_fence **fences = NULL; struct amdgpu_device *adev = (struct amdgpu_device *)data; @@ -1747,8 +1747,6 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val) /* stop the scheduler */ kthread_park(ring->sched.thread); - resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); - /* preempt the IB */ r = amdgpu_ring_preempt_ib(ring); if (r) { @@ -1785,8 +1783,6 @@ failure: up_read(&adev->reset_domain->sem); - ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched); - pro_end: kfree(fences); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b2b1c66bfe39..2b1db37e25c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3983,10 +3983,8 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) } amdgpu_fence_driver_hw_fini(adev); - if (adev->mman.initialized) { + if (adev->mman.initialized) flush_delayed_work(&adev->mman.bdev.wq); - ttm_bo_lock_delayed_workqueue(&adev->mman.bdev); - } if (adev->pm_sysfs_en) amdgpu_pm_sysfs_fini(adev); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 6344454a7721..9a556f505685 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1772,7 +1772,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) bool saved = false; int i, r; - int resched; down_write(&rdev->exclusive_lock); @@ -1784,8 +1783,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) atomic_inc(&rdev->gpu_reset_counter); radeon_save_bios_scratch_regs(rdev); - /* block TTM */ - resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); radeon_suspend(rdev); radeon_hpd_fini(rdev); @@ -1844,8 +1841,6 @@ int radeon_gpu_reset(struct radeon_device *rdev) /* reset hpd state */ radeon_hpd_init(rdev); - ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); - rdev->in_reset = true; rdev->needs_reset = false; diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 04c693ca419a..cbc554928bcc 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -1853,11 +1853,10 @@ static bool radeon_pm_debug_check_in_vbl(struct radeon_device *rdev, bool finish static void radeon_dynpm_idle_work_handler(struct work_struct *work) { struct radeon_device *rdev; - int resched; + rdev = container_of(work, struct radeon_device, pm.dynpm_idle_work.work); - resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev); mutex_lock(&rdev->pm.mutex); if (rdev->pm.dynpm_state == DYNPM_STATE_ACTIVE) { int not_processed = 0; @@ -1908,7 +1907,6 @@ static void radeon_dynpm_idle_work_handler(struct work_struct *work) msecs_to_jiffies(RADEON_IDLE_LOOP_MS)); } mutex_unlock(&rdev->pm.mutex); - ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched); } /* diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index c3f4b33136e5..b77262a623e0 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -418,20 +418,6 @@ void ttm_bo_put(struct ttm_buffer_object *bo) } EXPORT_SYMBOL(ttm_bo_put); -int ttm_bo_lock_delayed_workqueue(struct ttm_device *bdev) -{ - return cancel_delayed_work_sync(&bdev->wq); -} -EXPORT_SYMBOL(ttm_bo_lock_delayed_workqueue); - -void ttm_bo_unlock_delayed_workqueue(struct ttm_device *bdev, int resched) -{ - if (resched) - schedule_delayed_work(&bdev->wq, - ((HZ / 100) < 1) ? 1 : HZ / 100); -} -EXPORT_SYMBOL(ttm_bo_unlock_delayed_workqueue); - static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo, struct ttm_resource **mem, struct ttm_operation_ctx *ctx, diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 44a538ee5e2a..7758347c461c 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -290,22 +290,6 @@ void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo); void ttm_bo_set_bulk_move(struct ttm_buffer_object *bo, struct ttm_lru_bulk_move *bulk); -/** - * ttm_bo_lock_delayed_workqueue - * - * Prevent the delayed workqueue from running. - * Returns - * True if the workqueue was queued at the time - */ -int ttm_bo_lock_delayed_workqueue(struct ttm_device *bdev); - -/** - * ttm_bo_unlock_delayed_workqueue - * - * Allows the delayed workqueue to run. - */ -void ttm_bo_unlock_delayed_workqueue(struct ttm_device *bdev, int resched); - /** * ttm_bo_eviction_valuable * -- cgit v1.2.3 From 9bff18d13473a9fdf81d5158248472a9d8ecf2bd Mon Sep 17 00:00:00 2001 From: Christian König Date: Wed, 23 Nov 2022 10:14:56 +0100 Subject: drm/ttm: use per BO cleanup workers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of a single worker going over the list of delete BOs in regular intervals use a per BO worker which blocks for the resv object and locking of the BO. This not only simplifies the handling massively, but also results in much better response time when cleaning up buffers. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Reviewed-by: Arunpravin Paneer Selvam Link: https://patchwork.freedesktop.org/patch/msgid/20221125102137.1801-3-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/intel_region_ttm.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 112 +++++++++++------------------ drivers/gpu/drm/ttm/ttm_bo_util.c | 1 - drivers/gpu/drm/ttm/ttm_device.c | 24 +++---- include/drm/ttm/ttm_bo_api.h | 18 ++--- include/drm/ttm/ttm_device.h | 7 +- 8 files changed, 57 insertions(+), 111 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2b1db37e25c1..74ccbd566777 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -3984,7 +3984,7 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev) amdgpu_fence_driver_hw_fini(adev); if (adev->mman.initialized) - flush_delayed_work(&adev->mman.bdev.wq); + drain_workqueue(adev->mman.bdev.wq); if (adev->pm_sysfs_en) amdgpu_pm_sysfs_fini(adev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8468ca9885fd..c38306f156d6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1099,7 +1099,7 @@ void i915_gem_drain_freed_objects(struct drm_i915_private *i915) { while (atomic_read(&i915->mm.free_count)) { flush_work(&i915->mm.free_work); - flush_delayed_work(&i915->bdev.wq); + drain_workqueue(i915->bdev.wq); rcu_barrier(); } } diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c index cf89d0c2a2d9..657bbc16a48a 100644 --- a/drivers/gpu/drm/i915/intel_region_ttm.c +++ b/drivers/gpu/drm/i915/intel_region_ttm.c @@ -132,7 +132,7 @@ int intel_region_ttm_fini(struct intel_memory_region *mem) break; msleep(20); - flush_delayed_work(&mem->i915->bdev.wq); + drain_workqueue(mem->i915->bdev.wq); } /* If we leaked objects, Don't free the region causing use after free */ diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index b77262a623e0..4749b65bedc4 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -280,14 +280,13 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, ret = 0; } - if (ret || unlikely(list_empty(&bo->ddestroy))) { + if (ret) { if (unlock_resv) dma_resv_unlock(bo->base.resv); spin_unlock(&bo->bdev->lru_lock); return ret; } - list_del_init(&bo->ddestroy); spin_unlock(&bo->bdev->lru_lock); ttm_bo_cleanup_memtype_use(bo); @@ -300,47 +299,21 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, } /* - * Traverse the delayed list, and call ttm_bo_cleanup_refs on all - * encountered buffers. + * Block for the dma_resv object to become idle, lock the buffer and clean up + * the resource and tt object. */ -bool ttm_bo_delayed_delete(struct ttm_device *bdev, bool remove_all) +static void ttm_bo_delayed_delete(struct work_struct *work) { - struct list_head removed; - bool empty; - - INIT_LIST_HEAD(&removed); - - spin_lock(&bdev->lru_lock); - while (!list_empty(&bdev->ddestroy)) { - struct ttm_buffer_object *bo; - - bo = list_first_entry(&bdev->ddestroy, struct ttm_buffer_object, - ddestroy); - list_move_tail(&bo->ddestroy, &removed); - if (!ttm_bo_get_unless_zero(bo)) - continue; - - if (remove_all || bo->base.resv != &bo->base._resv) { - spin_unlock(&bdev->lru_lock); - dma_resv_lock(bo->base.resv, NULL); - - spin_lock(&bdev->lru_lock); - ttm_bo_cleanup_refs(bo, false, !remove_all, true); - - } else if (dma_resv_trylock(bo->base.resv)) { - ttm_bo_cleanup_refs(bo, false, !remove_all, true); - } else { - spin_unlock(&bdev->lru_lock); - } + struct ttm_buffer_object *bo; - ttm_bo_put(bo); - spin_lock(&bdev->lru_lock); - } - list_splice_tail(&removed, &bdev->ddestroy); - empty = list_empty(&bdev->ddestroy); - spin_unlock(&bdev->lru_lock); + bo = container_of(work, typeof(*bo), delayed_delete); - return empty; + dma_resv_wait_timeout(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP, false, + MAX_SCHEDULE_TIMEOUT); + dma_resv_lock(bo->base.resv, NULL); + ttm_bo_cleanup_memtype_use(bo); + dma_resv_unlock(bo->base.resv); + ttm_bo_put(bo); } static void ttm_bo_release(struct kref *kref) @@ -369,44 +342,40 @@ static void ttm_bo_release(struct kref *kref) drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node); ttm_mem_io_free(bdev, bo->resource); - } - - if (!dma_resv_test_signaled(bo->base.resv, DMA_RESV_USAGE_BOOKKEEP) || - !dma_resv_trylock(bo->base.resv)) { - /* The BO is not idle, resurrect it for delayed destroy */ - ttm_bo_flush_all_fences(bo); - bo->deleted = true; - spin_lock(&bo->bdev->lru_lock); + if (!dma_resv_test_signaled(bo->base.resv, + DMA_RESV_USAGE_BOOKKEEP) || + !dma_resv_trylock(bo->base.resv)) { + /* The BO is not idle, resurrect it for delayed destroy */ + ttm_bo_flush_all_fences(bo); + bo->deleted = true; - /* - * Make pinned bos immediately available to - * shrinkers, now that they are queued for - * destruction. - * - * FIXME: QXL is triggering this. Can be removed when the - * driver is fixed. - */ - if (bo->pin_count) { - bo->pin_count = 0; - ttm_resource_move_to_lru_tail(bo->resource); - } + spin_lock(&bo->bdev->lru_lock); - kref_init(&bo->kref); - list_add_tail(&bo->ddestroy, &bdev->ddestroy); - spin_unlock(&bo->bdev->lru_lock); + /* + * Make pinned bos immediately available to + * shrinkers, now that they are queued for + * destruction. + * + * FIXME: QXL is triggering this. Can be removed when the + * driver is fixed. + */ + if (bo->pin_count) { + bo->pin_count = 0; + ttm_resource_move_to_lru_tail(bo->resource); + } - schedule_delayed_work(&bdev->wq, - ((HZ / 100) < 1) ? 1 : HZ / 100); - return; - } + kref_init(&bo->kref); + spin_unlock(&bo->bdev->lru_lock); - spin_lock(&bo->bdev->lru_lock); - list_del(&bo->ddestroy); - spin_unlock(&bo->bdev->lru_lock); + INIT_WORK(&bo->delayed_delete, ttm_bo_delayed_delete); + queue_work(bdev->wq, &bo->delayed_delete); + return; + } - ttm_bo_cleanup_memtype_use(bo); - dma_resv_unlock(bo->base.resv); + ttm_bo_cleanup_memtype_use(bo); + dma_resv_unlock(bo->base.resv); + } atomic_dec(&ttm_glob.bo_count); bo->destroy(bo); @@ -946,7 +915,6 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, int ret; kref_init(&bo->kref); - INIT_LIST_HEAD(&bo->ddestroy); bo->bdev = bdev; bo->type = type; bo->page_alignment = alignment; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index ba3aa0a0fc43..ae4b7922ee1a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -230,7 +230,6 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, */ atomic_inc(&ttm_glob.bo_count); - INIT_LIST_HEAD(&fbo->base.ddestroy); drm_vma_node_reset(&fbo->base.base.vma_node); kref_init(&fbo->base.kref); diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index e7147e304637..e9bedca4dfdc 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -175,16 +175,6 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, } EXPORT_SYMBOL(ttm_device_swapout); -static void ttm_device_delayed_workqueue(struct work_struct *work) -{ - struct ttm_device *bdev = - container_of(work, struct ttm_device, wq.work); - - if (!ttm_bo_delayed_delete(bdev, false)) - schedule_delayed_work(&bdev->wq, - ((HZ / 100) < 1) ? 1 : HZ / 100); -} - /** * ttm_device_init * @@ -215,15 +205,19 @@ int ttm_device_init(struct ttm_device *bdev, struct ttm_device_funcs *funcs, if (ret) return ret; + bdev->wq = alloc_workqueue("ttm", WQ_MEM_RECLAIM | WQ_HIGHPRI, 16); + if (!bdev->wq) { + ttm_global_release(); + return -ENOMEM; + } + bdev->funcs = funcs; ttm_sys_man_init(bdev); ttm_pool_init(&bdev->pool, dev, use_dma_alloc, use_dma32); bdev->vma_manager = vma_manager; - INIT_DELAYED_WORK(&bdev->wq, ttm_device_delayed_workqueue); spin_lock_init(&bdev->lru_lock); - INIT_LIST_HEAD(&bdev->ddestroy); INIT_LIST_HEAD(&bdev->pinned); bdev->dev_mapping = mapping; mutex_lock(&ttm_global_mutex); @@ -247,10 +241,8 @@ void ttm_device_fini(struct ttm_device *bdev) list_del(&bdev->device_list); mutex_unlock(&ttm_global_mutex); - cancel_delayed_work_sync(&bdev->wq); - - if (ttm_bo_delayed_delete(bdev, true)) - pr_debug("Delayed destroy list was clean\n"); + drain_workqueue(bdev->wq); + destroy_workqueue(bdev->wq); spin_lock(&bdev->lru_lock); for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 7758347c461c..69e62bbb01e3 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -92,7 +92,6 @@ struct ttm_tt; * @ttm: TTM structure holding system pages. * @evicted: Whether the object was evicted without user-space knowing. * @deleted: True if the object is only a zombie and already deleted. - * @ddestroy: List head for the delayed destroy list. * @swap: List head for swap LRU list. * @offset: The current GPU offset, which can have different meanings * depending on the memory type. For SYSTEM type memory, it should be 0. @@ -135,19 +134,14 @@ struct ttm_buffer_object { struct ttm_tt *ttm; bool deleted; struct ttm_lru_bulk_move *bulk_move; + unsigned priority; + unsigned pin_count; /** - * Members protected by the bdev::lru_lock. - */ - - struct list_head ddestroy; - - /** - * Members protected by a bo reservation. + * @delayed_delete: Work item used when we can't delete the BO + * immediately */ - - unsigned priority; - unsigned pin_count; + struct work_struct delayed_delete; /** * Special members that are protected by the reserve lock @@ -448,8 +442,6 @@ void ttm_bo_vm_close(struct vm_area_struct *vma); int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr, void *buf, int len, int write); -bool ttm_bo_delayed_delete(struct ttm_device *bdev, bool remove_all); - vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot); #endif diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h index 95b3c04b1ab9..4f3e81eac6f3 100644 --- a/include/drm/ttm/ttm_device.h +++ b/include/drm/ttm/ttm_device.h @@ -251,11 +251,6 @@ struct ttm_device { */ spinlock_t lru_lock; - /** - * @ddestroy: Destroyed but not yet cleaned up buffer objects. - */ - struct list_head ddestroy; - /** * @pinned: Buffer objects which are pinned and so not on any LRU list. */ @@ -270,7 +265,7 @@ struct ttm_device { /** * @wq: Work queue structure for the delayed delete workqueue. */ - struct delayed_work wq; + struct workqueue_struct *wq; }; int ttm_global_swapout(struct ttm_operation_ctx *ctx, gfp_t gfp_flags); -- cgit v1.2.3 From a3185f91d0579b61a0a0dce3df1c67d6e324ebc8 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 9 May 2022 21:13:35 +0200 Subject: drm/ttm: merge ttm_bo_api.h and ttm_bo_driver.h v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge and cleanup the two headers into a single description of the object API. Also move all the documentation to the implementation and drop unnecessary includes from the header. No functional change. v2: minimal checkpatch.pl cleanup Signed-off-by: Christian König Reviewed-by: Arunpravin Paneer Selvam Link: https://patchwork.freedesktop.org/patch/msgid/20221125102137.1801-4-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h | 2 + drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 1 + drivers/gpu/drm/drm_gem_ttm_helper.c | 2 + drivers/gpu/drm/drm_gem_vram_helper.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_object_types.h | 2 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c | 2 +- drivers/gpu/drm/i915/i915_deps.c | 2 +- drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 2 +- drivers/gpu/drm/i915/intel_region_ttm.c | 1 - drivers/gpu/drm/nouveau/nouveau_bo.c | 1 + drivers/gpu/drm/nouveau/nouveau_bo.h | 3 +- drivers/gpu/drm/nouveau/nouveau_drv.h | 3 +- drivers/gpu/drm/nouveau/nouveau_mem.c | 3 +- drivers/gpu/drm/nouveau/nouveau_mem.h | 2 +- drivers/gpu/drm/nouveau/nouveau_prime.c | 1 + drivers/gpu/drm/nouveau/nouveau_sgdma.c | 1 + drivers/gpu/drm/qxl/qxl_drv.h | 3 +- drivers/gpu/drm/qxl/qxl_ttm.c | 4 +- drivers/gpu/drm/radeon/radeon.h | 3 +- drivers/gpu/drm/radeon/radeon_prime.c | 2 + drivers/gpu/drm/radeon/radeon_ttm.c | 4 +- drivers/gpu/drm/ttm/ttm_bo.c | 81 +++- drivers/gpu/drm/ttm/ttm_bo_util.c | 110 +++++- drivers/gpu/drm/ttm/ttm_bo_vm.c | 19 +- drivers/gpu/drm/ttm/ttm_device.c | 2 +- drivers/gpu/drm/ttm/ttm_execbuf_util.c | 6 +- drivers/gpu/drm/ttm/ttm_pool.c | 3 +- drivers/gpu/drm/ttm/ttm_range_manager.c | 2 +- drivers/gpu/drm/ttm/ttm_resource.c | 3 +- drivers/gpu/drm/ttm/ttm_tt.c | 3 +- drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c | 1 - drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 1 - include/drm/drm_gem_ttm_helper.h | 3 +- include/drm/drm_gem_vram_helper.h | 4 +- include/drm/ttm/ttm_bo.h | 430 ++++++++++++++++++++++ include/drm/ttm/ttm_bo_api.h | 447 ----------------------- include/drm/ttm/ttm_bo_driver.h | 303 --------------- include/drm/ttm/ttm_execbuf_util.h | 4 +- 56 files changed, 676 insertions(+), 823 deletions(-) create mode 100644 include/drm/ttm/ttm_bo.h delete mode 100644 include/drm/ttm/ttm_bo_api.h delete mode 100644 include/drm/ttm/ttm_bo_driver.h (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 6b74df446694..2644cd991210 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -52,8 +52,7 @@ #include #include -#include -#include +#include #include #include diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 3a763916a5a1..ab450f12c445 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "amdgpu_object.h" #include "amdgpu_gem.h" diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h index e4d78491bcc7..ededdc01ca28 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bo_list.h @@ -28,6 +28,8 @@ struct hmm_range; +struct drm_file; + struct amdgpu_device; struct amdgpu_bo; struct amdgpu_bo_va; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 8516c814bc9b..8b7a09b392ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -32,6 +32,8 @@ #include #include +#include + #include "amdgpu_cs.h" #include "amdgpu.h" #include "amdgpu_trace.h" diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h index 113f39510a72..fb3e3d56d427 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h @@ -23,6 +23,8 @@ #ifndef __AMDGPU_CS_H__ #define __AMDGPU_CS_H__ +#include + #include "amdgpu_job.h" #include "amdgpu_bo_list.h" #include "amdgpu_ring.h" diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 271e30e34d93..0c001bb8fc2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -37,6 +37,7 @@ #include "amdgpu_dma_buf.h" #include "amdgpu_xgmi.h" #include +#include #include #include #include diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h index 41a4c7056729..e86834bfea1d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fdinfo.h @@ -30,7 +30,6 @@ #include #include #include -#include #include #include "amdgpu_sync.h" diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index a0780a4e3e61..f8f9d68d69ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "amdgpu.h" #include "amdgpu_display.h" diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 4365ede42855..3169a942dbbb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -35,6 +35,7 @@ #include "amdgpu_xgmi.h" #include +#include /** * amdgpu_gmc_pdb0_alloc - allocate vram for pdb0 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 7b5074e776f4..068c2d8495fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -44,10 +44,10 @@ #include #include -#include -#include +#include #include #include +#include #include #include diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 003aa9e47085..fea25519227f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -33,6 +33,7 @@ #include #include +#include #include "amdgpu.h" #include "amdgpu_trace.h" #include "amdgpu_amdkfd.h" diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 6546e786bf00..44157c6c0804 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include "amdgpu_sync.h" diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 814f99888ab1..37219198d518 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -23,6 +23,7 @@ #include #include +#include #include "amdgpu_sync.h" #include "amdgpu_object.h" #include "amdgpu_vm.h" diff --git a/drivers/gpu/drm/drm_gem_ttm_helper.c b/drivers/gpu/drm/drm_gem_ttm_helper.c index d5962a34c01d..3734aa2d1c5b 100644 --- a/drivers/gpu/drm/drm_gem_ttm_helper.c +++ b/drivers/gpu/drm/drm_gem_ttm_helper.c @@ -3,6 +3,8 @@ #include #include +#include +#include /** * DOC: overview diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index b6c7e3803bb3..f59adffd938a 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -19,6 +19,7 @@ #include #include +#include static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index d0d6772e6f36..a7b70701617a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include "i915_active.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 1e50fb0d6bfc..5247d88b3c13 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -5,8 +5,8 @@ #include -#include #include +#include #include #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c index f59f812dc6d2..2ebaaf4d663c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c @@ -3,7 +3,7 @@ * Copyright © 2021 Intel Corporation */ -#include +#include #include "i915_deps.h" #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/i915_deps.c b/drivers/gpu/drm/i915/i915_deps.c index 297b8e4e42ee..91c61864285a 100644 --- a/drivers/gpu/drm/i915/i915_deps.c +++ b/drivers/gpu/drm/i915/i915_deps.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include "i915_deps.h" diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c index 7e611476c7a4..a72698a2dbc8 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -5,8 +5,8 @@ #include -#include #include +#include #include diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c index 657bbc16a48a..4dc0702081b8 100644 --- a/drivers/gpu/drm/i915/intel_region_ttm.c +++ b/drivers/gpu/drm/i915/intel_region_ttm.c @@ -2,7 +2,6 @@ /* * Copyright © 2021 Intel Corporation */ -#include #include #include diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index a11871e3119c..335fa91ca4ad 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -28,6 +28,7 @@ */ #include +#include #include "nouveau_drv.h" #include "nouveau_chan.h" diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index c2d3f9c48eba..774dd93ca76b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -1,8 +1,9 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NOUVEAU_BO_H__ #define __NOUVEAU_BO_H__ -#include #include +#include +#include struct nouveau_channel; struct nouveau_cli; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index d6dd07bfa64a..b5de312a523f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -51,8 +51,7 @@ #include #include -#include -#include +#include #include #include diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index 1fde3a5d7c32..25f31d5169e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -19,11 +19,12 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ +#include + #include "nouveau_mem.h" #include "nouveau_drv.h" #include "nouveau_bo.h" -#include #include #include diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.h b/drivers/gpu/drm/nouveau/nouveau_mem.h index 1ee6cdb9ad9b..76c86d8bb01e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.h +++ b/drivers/gpu/drm/nouveau/nouveau_mem.h @@ -1,6 +1,6 @@ #ifndef __NOUVEAU_MEM_H__ #define __NOUVEAU_MEM_H__ -#include +#include struct ttm_tt; #include diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 9608121e49b7..f42c2b1b0363 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -23,6 +23,7 @@ */ #include +#include #include "nouveau_drv.h" #include "nouveau_gem.h" diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 85c03c83259b..b14895f75b3c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT #include #include +#include #include "nouveau_drv.h" #include "nouveau_mem.h" diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 76f060810f63..ea993d7162e8 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -42,8 +42,7 @@ #include #include #include -#include -#include +#include #include #include diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index ee95001e6b5e..a92a5b0d4c25 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -29,10 +29,10 @@ #include #include #include -#include -#include +#include #include #include +#include #include "qxl_drv.h" #include "qxl_object.h" diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 2e7161acd443..57e20780a458 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -73,8 +73,7 @@ #include #endif -#include -#include +#include #include #include diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c index 42a87948e28c..b3cfc99f4d7e 100644 --- a/drivers/gpu/drm/radeon/radeon_prime.c +++ b/drivers/gpu/drm/radeon/radeon_prime.c @@ -29,6 +29,8 @@ #include #include +#include + #include "radeon.h" #include "radeon_prime.h" diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 30402b5ce4c5..1e8e287e113c 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -42,10 +42,10 @@ #include #include #include -#include -#include +#include #include #include +#include #include "radeon_reg.h" #include "radeon.h" diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 4749b65bedc4..f9d9fd2d865d 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -31,8 +31,10 @@ #define pr_fmt(fmt) "[TTM] " fmt -#include +#include #include +#include + #include #include #include @@ -381,6 +383,13 @@ static void ttm_bo_release(struct kref *kref) bo->destroy(bo); } +/** + * ttm_bo_put + * + * @bo: The buffer object. + * + * Unreference a buffer object. + */ void ttm_bo_put(struct ttm_buffer_object *bo) { kref_put(&bo->kref, ttm_bo_release); @@ -467,6 +476,14 @@ out: return ret; } +/** + * ttm_bo_eviction_valuable + * + * @bo: The buffer object to evict + * @place: the placement we need to make room for + * + * Check if it is valuable to evict the BO to make room for the given placement. + */ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, const struct ttm_place *place) { @@ -726,13 +743,23 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, return ttm_bo_add_move_fence(bo, man, *mem, ctx->no_wait_gpu); } -/* - * Creates space for memory region @mem according to its type. +/** + * ttm_bo_mem_space * - * This function first searches for free space in compatible memory types in - * the priority order defined by the driver. If free space isn't found, then - * ttm_bo_mem_force_space is attempted in priority order to evict and find - * space. + * @bo: Pointer to a struct ttm_buffer_object. the data of which + * we want to allocate space for. + * @proposed_placement: Proposed new placement for the buffer object. + * @mem: A struct ttm_resource. + * @ctx: if and how to sleep, lock buffers and alloc memory + * + * Allocate memory space for the buffer object pointed to by @bo, using + * the placement flags in @placement, potentially evicting other idle buffer objects. + * This function may sleep while waiting for space to become available. + * Returns: + * -EBUSY: No space available (only if no_wait == 1). + * -ENOMEM: Could not allocate memory for the buffer object, either due to + * fragmentation or concurrent allocators. + * -ERESTARTSYS: An interruptible sleep was interrupted by a signal. */ int ttm_bo_mem_space(struct ttm_buffer_object *bo, struct ttm_placement *placement, @@ -838,6 +865,21 @@ out: return ret; } +/** + * ttm_bo_validate + * + * @bo: The buffer object. + * @placement: Proposed placement for the buffer object. + * @ctx: validation parameters. + * + * Changes placement and caching policy of the buffer object + * according proposed placement. + * Returns + * -EINVAL on invalid proposed placement. + * -ENOMEM on out-of-memory condition. + * -EBUSY if no_wait is true and buffer busy. + * -ERESTARTSYS if interrupted by a signal. + */ int ttm_bo_validate(struct ttm_buffer_object *bo, struct ttm_placement *placement, struct ttm_operation_ctx *ctx) @@ -1030,6 +1072,11 @@ EXPORT_SYMBOL(ttm_bo_init_validate); * buffer object vm functions. */ +/** + * ttm_bo_unmap_virtual + * + * @bo: tear down the virtual mappings for this BO + */ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) { struct ttm_device *bdev = bo->bdev; @@ -1039,6 +1086,20 @@ void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo) } EXPORT_SYMBOL(ttm_bo_unmap_virtual); +/** + * ttm_bo_wait - wait for buffer idle. + * + * @bo: The buffer object. + * @interruptible: Use interruptible wait. + * @no_wait: Return immediately if buffer is busy. + * + * This function must be called with the bo::mutex held, and makes + * sure any previous rendering to the buffer is completed. + * Note: It might be necessary to block validations before the + * wait by reserving the buffer. + * Returns -EBUSY if no_wait is true and the buffer is busy. + * Returns -ERESTARTSYS if interrupted by a signal. + */ int ttm_bo_wait(struct ttm_buffer_object *bo, bool interruptible, bool no_wait) { @@ -1063,6 +1124,12 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_wait); +int ttm_bo_wait_ctx(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) +{ + return ttm_bo_wait(bo, ctx->interruptible, ctx->no_wait_gpu); +} +EXPORT_SYMBOL(ttm_bo_wait_ctx); + int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, gfp_t gfp_flags) { diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index ae4b7922ee1a..fee7c20775c0 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -29,18 +29,11 @@ * Authors: Thomas Hellstrom */ -#include +#include #include +#include + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include struct ttm_transfer_obj { struct ttm_buffer_object base; @@ -128,6 +121,23 @@ void ttm_move_memcpy(bool clear, } EXPORT_SYMBOL(ttm_move_memcpy); +/** + * ttm_bo_move_memcpy + * + * @bo: A pointer to a struct ttm_buffer_object. + * @interruptible: Sleep interruptible if waiting. + * @no_wait_gpu: Return immediately if the GPU is busy. + * @new_mem: struct ttm_resource indicating where to move. + * + * Fallback move function for a mappable buffer object in mappable memory. + * The function will, if successful, + * free any old aperture space, and set (@new_mem)->mm_node to NULL, + * and update the (@bo)->mem placement flags. If unsuccessful, the old + * data remains untouched, and it's up to the caller to free the + * memory space indicated by @new_mem. + * Returns: + * !0: Failure. + */ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, struct ttm_resource *dst_mem) @@ -266,6 +276,16 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, return 0; } +/** + * ttm_io_prot + * + * bo: ttm buffer object + * res: ttm resource object + * @tmp: Page protection flag for a normal, cached mapping. + * + * Utility function that returns the pgprot_t that should be used for + * setting up a PTE with the caching model indicated by @c_state. + */ pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res, pgprot_t tmp) { @@ -347,6 +367,22 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, return (!map->virtual) ? -ENOMEM : 0; } +/** + * ttm_bo_kmap + * + * @bo: The buffer object. + * @start_page: The first page to map. + * @num_pages: Number of pages to map. + * @map: pointer to a struct ttm_bo_kmap_obj representing the map. + * + * Sets up a kernel virtual mapping, using ioremap, vmap or kmap to the + * data in the buffer object. The ttm_kmap_obj_virtual function can then be + * used to obtain a virtual address to the data. + * + * Returns + * -ENOMEM: Out of memory. + * -EINVAL: Invalid range. + */ int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page, unsigned long num_pages, struct ttm_bo_kmap_obj *map) @@ -374,6 +410,13 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_kmap); +/** + * ttm_bo_kunmap + * + * @map: Object describing the map to unmap. + * + * Unmaps a kernel map set up by ttm_bo_kmap. + */ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) { if (!map->virtual) @@ -399,6 +442,20 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) } EXPORT_SYMBOL(ttm_bo_kunmap); +/** + * ttm_bo_vmap + * + * @bo: The buffer object. + * @map: pointer to a struct iosys_map representing the map. + * + * Sets up a kernel virtual mapping, using ioremap or vmap to the + * data in the buffer object. The parameter @map returns the virtual + * address as struct iosys_map. Unmap the buffer with ttm_bo_vunmap(). + * + * Returns + * -ENOMEM: Out of memory. + * -EINVAL: Invalid range. + */ int ttm_bo_vmap(struct ttm_buffer_object *bo, struct iosys_map *map) { struct ttm_resource *mem = bo->resource; @@ -460,6 +517,14 @@ int ttm_bo_vmap(struct ttm_buffer_object *bo, struct iosys_map *map) } EXPORT_SYMBOL(ttm_bo_vmap); +/** + * ttm_bo_vunmap + * + * @bo: The buffer object. + * @map: Object describing the map to unmap. + * + * Unmaps a kernel map set up by ttm_bo_vmap(). + */ void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct iosys_map *map) { struct ttm_resource *mem = bo->resource; @@ -553,6 +618,22 @@ static void ttm_bo_move_pipeline_evict(struct ttm_buffer_object *bo, ttm_resource_free(bo, &bo->resource); } +/** + * ttm_bo_move_accel_cleanup. + * + * @bo: A pointer to a struct ttm_buffer_object. + * @fence: A fence object that signals when moving is complete. + * @evict: This is an evict move. Don't return until the buffer is idle. + * @pipeline: evictions are to be pipelined. + * @new_mem: struct ttm_resource indicating where to move. + * + * Accelerated move function to be called when an accelerated move + * has been scheduled. The function will create a new temporary buffer object + * representing the old placement, and put the sync object on both buffer + * objects. After that the newly created buffer object is unref'd to be + * destroyed when the move is complete. This will help pipeline + * buffer moves. + */ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, struct dma_fence *fence, bool evict, @@ -581,6 +662,15 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, } EXPORT_SYMBOL(ttm_bo_move_accel_cleanup); +/** + * ttm_bo_move_sync_cleanup. + * + * @bo: A pointer to a struct ttm_buffer_object. + * @new_mem: struct ttm_resource indicating where to move. + * + * Special case of ttm_bo_move_accel_cleanup where the bo is guaranteed + * by the caller to be idle. Typically used after memcpy buffer moves. + */ void ttm_bo_move_sync_cleanup(struct ttm_buffer_object *bo, struct ttm_resource *new_mem) { diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 5a3e4b891377..3ecda6db24b8 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -31,17 +31,12 @@ #define pr_fmt(fmt) "[TTM] " fmt -#include +#include #include -#include +#include + #include #include -#include -#include -#include -#include -#include -#include static vm_fault_t ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo, struct vm_fault *vmf) @@ -446,6 +441,14 @@ static const struct vm_operations_struct ttm_bo_vm_ops = { .access = ttm_bo_vm_access, }; +/** + * ttm_bo_mmap_obj - mmap memory backed by a ttm buffer object. + * + * @vma: vma as input from the fbdev mmap method. + * @bo: The bo backing the address space. + * + * Maps a buffer object. + */ int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo) { /* Enforce no COW since would have really strange behavior with it. */ diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index e9bedca4dfdc..c7a1862f322a 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -29,10 +29,10 @@ #include +#include #include #include #include -#include #include "ttm_module.h" diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index dbee34a058df..f1c60fa80c2d 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -27,11 +27,7 @@ **************************************************************************/ #include -#include -#include -#include -#include -#include +#include static void ttm_eu_backoff_reservation_reverse(struct list_head *list, struct ttm_validate_buffer *entry) diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index 9f6764bf3b15..aa116a7bbae3 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -41,8 +42,8 @@ #endif #include -#include #include +#include #include "ttm_module.h" diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index 0a8bc0b7f380..ae11d07eb63a 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 328391bb1d87..b8a826a24fb2 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -26,8 +26,9 @@ #include #include +#include +#include #include -#include /** * ttm_lru_bulk_move_init - initialize a bulk move structure diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index d505603930a7..ab725d9d14a6 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -36,7 +36,8 @@ #include #include #include -#include +#include +#include #include "ttm_module.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c index 3c06df2a5474..2b843ff4b437 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c @@ -28,7 +28,7 @@ #include #include -#include +#include #include "vmwgfx_drv.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index bd02cb0e6837..9ad28346aff7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index b062b020b378..4b612fc9758c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -37,8 +37,10 @@ #include #include -#include #include +#include +#include +#include #include "ttm_object.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index a5379f6fb5ab..43cec8e37e4d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -29,7 +29,7 @@ #include "vmwgfx_drv.h" #include "vmwgfx_reg.h" -#include +#include #include #include "vmwgfx_so.h" #include "vmwgfx_binding.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index c482e5298e11..20158a92acc7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c @@ -25,7 +25,6 @@ * **************************************************************************/ -#include #include "vmwgfx_drv.h" diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c index abd5e3323ebf..ceb4d3d3b965 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c @@ -29,7 +29,6 @@ */ #include "vmwgfx_drv.h" -#include #include #include #include diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c index d3007bf1b8f5..ee7964cbdaca 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_system_manager.c @@ -26,7 +26,6 @@ #include "vmwgfx_drv.h" -#include #include #include #include diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 4e3938e62c08..856a352a72a6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -26,7 +26,6 @@ **************************************************************************/ #include "vmwgfx_drv.h" -#include #include static const struct ttm_place vram_placement_flags = { diff --git a/include/drm/drm_gem_ttm_helper.h b/include/drm/drm_gem_ttm_helper.h index 4c003b4f173e..7b53d673ae7e 100644 --- a/include/drm/drm_gem_ttm_helper.h +++ b/include/drm/drm_gem_ttm_helper.h @@ -7,8 +7,7 @@ #include #include -#include -#include +#include struct iosys_map; diff --git a/include/drm/drm_gem_vram_helper.h b/include/drm/drm_gem_vram_helper.h index c083a1d71cf4..d3e8920c0b64 100644 --- a/include/drm/drm_gem_vram_helper.h +++ b/include/drm/drm_gem_vram_helper.h @@ -8,8 +8,8 @@ #include #include #include -#include -#include +#include +#include #include #include diff --git a/include/drm/ttm/ttm_bo.h b/include/drm/ttm/ttm_bo.h new file mode 100644 index 000000000000..d87232472435 --- /dev/null +++ b/include/drm/ttm/ttm_bo.h @@ -0,0 +1,430 @@ +/************************************************************************** + * + * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ +/* + * Authors: Thomas Hellstrom + */ + +#ifndef _TTM_BO_API_H_ +#define _TTM_BO_API_H_ + +#include + +#include +#include + +#include "ttm_device.h" + +/* Default number of pre-faulted pages in the TTM fault handler */ +#define TTM_BO_VM_NUM_PREFAULT 16 + +struct iosys_map; + +struct ttm_global; +struct ttm_device; +struct ttm_placement; +struct ttm_place; +struct ttm_resource; +struct ttm_resource_manager; +struct ttm_tt; + +/** + * enum ttm_bo_type + * + * @ttm_bo_type_device: These are 'normal' buffers that can + * be mmapped by user space. Each of these bos occupy a slot in the + * device address space, that can be used for normal vm operations. + * + * @ttm_bo_type_kernel: These buffers are like ttm_bo_type_device buffers, + * but they cannot be accessed from user-space. For kernel-only use. + * + * @ttm_bo_type_sg: Buffer made from dmabuf sg table shared with another + * driver. + */ +enum ttm_bo_type { + ttm_bo_type_device, + ttm_bo_type_kernel, + ttm_bo_type_sg +}; + +/** + * struct ttm_buffer_object + * + * @base: drm_gem_object superclass data. + * @bdev: Pointer to the buffer object device structure. + * @type: The bo type. + * @page_alignment: Page alignment. + * @destroy: Destruction function. If NULL, kfree is used. + * @kref: Reference count of this buffer object. When this refcount reaches + * zero, the object is destroyed or put on the delayed delete list. + * @resource: structure describing current placement. + * @ttm: TTM structure holding system pages. + * @deleted: True if the object is only a zombie and already deleted. + * + * Base class for TTM buffer object, that deals with data placement and CPU + * mappings. GPU mappings are really up to the driver, but for simpler GPUs + * the driver can usually use the placement offset @offset directly as the + * GPU virtual address. For drivers implementing multiple + * GPU memory manager contexts, the driver should manage the address space + * in these contexts separately and use these objects to get the correct + * placement and caching for these GPU maps. This makes it possible to use + * these objects for even quite elaborate memory management schemes. + * The destroy member, the API visibility of this object makes it possible + * to derive driver specific types. + */ +struct ttm_buffer_object { + struct drm_gem_object base; + + /* + * Members constant at init. + */ + struct ttm_device *bdev; + enum ttm_bo_type type; + uint32_t page_alignment; + void (*destroy) (struct ttm_buffer_object *); + + /* + * Members not needing protection. + */ + struct kref kref; + + /* + * Members protected by the bo::resv::reserved lock. + */ + struct ttm_resource *resource; + struct ttm_tt *ttm; + bool deleted; + struct ttm_lru_bulk_move *bulk_move; + unsigned priority; + unsigned pin_count; + + /** + * @delayed_delete: Work item used when we can't delete the BO + * immediately + */ + struct work_struct delayed_delete; + + /** + * Special members that are protected by the reserve lock + * and the bo::lock when written to. Can be read with + * either of these locks held. + */ + struct sg_table *sg; +}; + +/** + * struct ttm_bo_kmap_obj + * + * @virtual: The current kernel virtual address. + * @page: The page when kmap'ing a single page. + * @bo_kmap_type: Type of bo_kmap. + * + * Object describing a kernel mapping. Since a TTM bo may be located + * in various memory types with various caching policies, the + * mapping can either be an ioremap, a vmap, a kmap or part of a + * premapped region. + */ +#define TTM_BO_MAP_IOMEM_MASK 0x80 +struct ttm_bo_kmap_obj { + void *virtual; + struct page *page; + enum { + ttm_bo_map_iomap = 1 | TTM_BO_MAP_IOMEM_MASK, + ttm_bo_map_vmap = 2, + ttm_bo_map_kmap = 3, + ttm_bo_map_premapped = 4 | TTM_BO_MAP_IOMEM_MASK, + } bo_kmap_type; + struct ttm_buffer_object *bo; +}; + +/** + * struct ttm_operation_ctx + * + * @interruptible: Sleep interruptible if sleeping. + * @no_wait_gpu: Return immediately if the GPU is busy. + * @gfp_retry_mayfail: Set the __GFP_RETRY_MAYFAIL when allocation pages. + * @allow_res_evict: Allow eviction of reserved BOs. Can be used when multiple + * BOs share the same reservation object. + * @force_alloc: Don't check the memory account during suspend or CPU page + * faults. Should only be used by TTM internally. + * @resv: Reservation object to allow reserved evictions with. + * + * Context for TTM operations like changing buffer placement or general memory + * allocation. + */ +struct ttm_operation_ctx { + bool interruptible; + bool no_wait_gpu; + bool gfp_retry_mayfail; + bool allow_res_evict; + bool force_alloc; + struct dma_resv *resv; + uint64_t bytes_moved; +}; + +/** + * ttm_bo_get - reference a struct ttm_buffer_object + * + * @bo: The buffer object. + */ +static inline void ttm_bo_get(struct ttm_buffer_object *bo) +{ + kref_get(&bo->kref); +} + +/** + * ttm_bo_get_unless_zero - reference a struct ttm_buffer_object unless + * its refcount has already reached zero. + * @bo: The buffer object. + * + * Used to reference a TTM buffer object in lookups where the object is removed + * from the lookup structure during the destructor and for RCU lookups. + * + * Returns: @bo if the referencing was successful, NULL otherwise. + */ +static inline __must_check struct ttm_buffer_object * +ttm_bo_get_unless_zero(struct ttm_buffer_object *bo) +{ + if (!kref_get_unless_zero(&bo->kref)) + return NULL; + return bo; +} + +/** + * ttm_bo_reserve: + * + * @bo: A pointer to a struct ttm_buffer_object. + * @interruptible: Sleep interruptible if waiting. + * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. + * @ticket: ticket used to acquire the ww_mutex. + * + * Locks a buffer object for validation. (Or prevents other processes from + * locking it for validation), while taking a number of measures to prevent + * deadlocks. + * + * Returns: + * -EDEADLK: The reservation may cause a deadlock. + * Release all buffer reservations, wait for @bo to become unreserved and + * try again. + * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by + * a signal. Release all buffer reservations and return to user-space. + * -EBUSY: The function needed to sleep, but @no_wait was true + * -EALREADY: Bo already reserved using @ticket. This error code will only + * be returned if @use_ticket is set to true. + */ +static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, + bool interruptible, bool no_wait, + struct ww_acquire_ctx *ticket) +{ + int ret = 0; + + if (no_wait) { + bool success; + + if (WARN_ON(ticket)) + return -EBUSY; + + success = dma_resv_trylock(bo->base.resv); + return success ? 0 : -EBUSY; + } + + if (interruptible) + ret = dma_resv_lock_interruptible(bo->base.resv, ticket); + else + ret = dma_resv_lock(bo->base.resv, ticket); + if (ret == -EINTR) + return -ERESTARTSYS; + return ret; +} + +/** + * ttm_bo_reserve_slowpath: + * @bo: A pointer to a struct ttm_buffer_object. + * @interruptible: Sleep interruptible if waiting. + * @sequence: Set (@bo)->sequence to this value after lock + * + * This is called after ttm_bo_reserve returns -EAGAIN and we backed off + * from all our other reservations. Because there are no other reservations + * held by us, this function cannot deadlock any more. + */ +static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, + bool interruptible, + struct ww_acquire_ctx *ticket) +{ + if (interruptible) { + int ret = dma_resv_lock_slow_interruptible(bo->base.resv, + ticket); + if (ret == -EINTR) + ret = -ERESTARTSYS; + return ret; + } + dma_resv_lock_slow(bo->base.resv, ticket); + return 0; +} + +void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo); + +static inline void +ttm_bo_move_to_lru_tail_unlocked(struct ttm_buffer_object *bo) +{ + spin_lock(&bo->bdev->lru_lock); + ttm_bo_move_to_lru_tail(bo); + spin_unlock(&bo->bdev->lru_lock); +} + +static inline void ttm_bo_assign_mem(struct ttm_buffer_object *bo, + struct ttm_resource *new_mem) +{ + WARN_ON(bo->resource); + bo->resource = new_mem; +} + +/** + * ttm_bo_move_null = assign memory for a buffer object. + * @bo: The bo to assign the memory to + * @new_mem: The memory to be assigned. + * + * Assign the memory from new_mem to the memory of the buffer object bo. + */ +static inline void ttm_bo_move_null(struct ttm_buffer_object *bo, + struct ttm_resource *new_mem) +{ + ttm_resource_free(bo, &bo->resource); + ttm_bo_assign_mem(bo, new_mem); +} + +/** + * ttm_bo_unreserve + * + * @bo: A pointer to a struct ttm_buffer_object. + * + * Unreserve a previous reservation of @bo. + */ +static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) +{ + ttm_bo_move_to_lru_tail_unlocked(bo); + dma_resv_unlock(bo->base.resv); +} + +/** + * ttm_kmap_obj_virtual + * + * @map: A struct ttm_bo_kmap_obj returned from ttm_bo_kmap. + * @is_iomem: Pointer to an integer that on return indicates 1 if the + * virtual map is io memory, 0 if normal memory. + * + * Returns the virtual address of a buffer object area mapped by ttm_bo_kmap. + * If *is_iomem is 1 on return, the virtual address points to an io memory area, + * that should strictly be accessed by the iowriteXX() and similar functions. + */ +static inline void *ttm_kmap_obj_virtual(struct ttm_bo_kmap_obj *map, + bool *is_iomem) +{ + *is_iomem = !!(map->bo_kmap_type & TTM_BO_MAP_IOMEM_MASK); + return map->virtual; +} + +int ttm_bo_wait(struct ttm_buffer_object *bo, bool interruptible, bool no_wait); +int ttm_bo_wait_ctx(struct ttm_buffer_object *bo, + struct ttm_operation_ctx *ctx); +int ttm_bo_validate(struct ttm_buffer_object *bo, + struct ttm_placement *placement, + struct ttm_operation_ctx *ctx); +void ttm_bo_put(struct ttm_buffer_object *bo); +void ttm_bo_set_bulk_move(struct ttm_buffer_object *bo, + struct ttm_lru_bulk_move *bulk); +int ttm_bo_lock_delayed_workqueue(struct ttm_device *bdev); +void ttm_bo_unlock_delayed_workqueue(struct ttm_device *bdev, int resched); +bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, + const struct ttm_place *place); +int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, + enum ttm_bo_type type, struct ttm_placement *placement, + uint32_t alignment, struct ttm_operation_ctx *ctx, + struct sg_table *sg, struct dma_resv *resv, + void (*destroy)(struct ttm_buffer_object *)); +int ttm_bo_init_validate(struct ttm_device *bdev, struct ttm_buffer_object *bo, + enum ttm_bo_type type, struct ttm_placement *placement, + uint32_t alignment, bool interruptible, + struct sg_table *sg, struct dma_resv *resv, + void (*destroy)(struct ttm_buffer_object *)); +int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page, + unsigned long num_pages, struct ttm_bo_kmap_obj *map); +void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map); +int ttm_bo_vmap(struct ttm_buffer_object *bo, struct iosys_map *map); +void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct iosys_map *map); +int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo); +int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, + gfp_t gfp_flags); +void ttm_bo_pin(struct ttm_buffer_object *bo); +void ttm_bo_unpin(struct ttm_buffer_object *bo); +int ttm_mem_evict_first(struct ttm_device *bdev, + struct ttm_resource_manager *man, + const struct ttm_place *place, + struct ttm_operation_ctx *ctx, + struct ww_acquire_ctx *ticket); +vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo, + struct vm_fault *vmf); +vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, + pgprot_t prot, + pgoff_t num_prefault); +vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf); +void ttm_bo_vm_open(struct vm_area_struct *vma); +void ttm_bo_vm_close(struct vm_area_struct *vma); +int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr, + void *buf, int len, int write); +vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot); + +int ttm_bo_mem_space(struct ttm_buffer_object *bo, + struct ttm_placement *placement, + struct ttm_resource **mem, + struct ttm_operation_ctx *ctx); + +void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); +/* + * ttm_bo_util.c + */ +int ttm_mem_io_reserve(struct ttm_device *bdev, + struct ttm_resource *mem); +void ttm_mem_io_free(struct ttm_device *bdev, + struct ttm_resource *mem); +void ttm_move_memcpy(bool clear, u32 num_pages, + struct ttm_kmap_iter *dst_iter, + struct ttm_kmap_iter *src_iter); +int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, + struct ttm_operation_ctx *ctx, + struct ttm_resource *new_mem); +int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, + struct dma_fence *fence, bool evict, + bool pipeline, + struct ttm_resource *new_mem); +void ttm_bo_move_sync_cleanup(struct ttm_buffer_object *bo, + struct ttm_resource *new_mem); +int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo); +pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res, + pgprot_t tmp); +void ttm_bo_tt_destroy(struct ttm_buffer_object *bo); + +#endif diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h deleted file mode 100644 index 69e62bbb01e3..000000000000 --- a/include/drm/ttm/ttm_bo_api.h +++ /dev/null @@ -1,447 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom - */ - -#ifndef _TTM_BO_API_H_ -#define _TTM_BO_API_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ttm_resource.h" - -struct ttm_global; - -struct ttm_device; - -struct iosys_map; - -struct drm_mm_node; - -struct ttm_placement; - -struct ttm_place; - -/** - * enum ttm_bo_type - * - * @ttm_bo_type_device: These are 'normal' buffers that can - * be mmapped by user space. Each of these bos occupy a slot in the - * device address space, that can be used for normal vm operations. - * - * @ttm_bo_type_kernel: These buffers are like ttm_bo_type_device buffers, - * but they cannot be accessed from user-space. For kernel-only use. - * - * @ttm_bo_type_sg: Buffer made from dmabuf sg table shared with another - * driver. - */ - -enum ttm_bo_type { - ttm_bo_type_device, - ttm_bo_type_kernel, - ttm_bo_type_sg -}; - -struct ttm_tt; - -/** - * struct ttm_buffer_object - * - * @base: drm_gem_object superclass data. - * @bdev: Pointer to the buffer object device structure. - * @type: The bo type. - * @page_alignment: Page alignment. - * @destroy: Destruction function. If NULL, kfree is used. - * @num_pages: Actual number of pages. - * @kref: Reference count of this buffer object. When this refcount reaches - * zero, the object is destroyed or put on the delayed delete list. - * @mem: structure describing current placement. - * @ttm: TTM structure holding system pages. - * @evicted: Whether the object was evicted without user-space knowing. - * @deleted: True if the object is only a zombie and already deleted. - * @swap: List head for swap LRU list. - * @offset: The current GPU offset, which can have different meanings - * depending on the memory type. For SYSTEM type memory, it should be 0. - * @cur_placement: Hint of current placement. - * - * Base class for TTM buffer object, that deals with data placement and CPU - * mappings. GPU mappings are really up to the driver, but for simpler GPUs - * the driver can usually use the placement offset @offset directly as the - * GPU virtual address. For drivers implementing multiple - * GPU memory manager contexts, the driver should manage the address space - * in these contexts separately and use these objects to get the correct - * placement and caching for these GPU maps. This makes it possible to use - * these objects for even quite elaborate memory management schemes. - * The destroy member, the API visibility of this object makes it possible - * to derive driver specific types. - */ - -struct ttm_buffer_object { - struct drm_gem_object base; - - /** - * Members constant at init. - */ - - struct ttm_device *bdev; - enum ttm_bo_type type; - uint32_t page_alignment; - void (*destroy) (struct ttm_buffer_object *); - - /** - * Members not needing protection. - */ - struct kref kref; - - /** - * Members protected by the bo::resv::reserved lock. - */ - - struct ttm_resource *resource; - struct ttm_tt *ttm; - bool deleted; - struct ttm_lru_bulk_move *bulk_move; - unsigned priority; - unsigned pin_count; - - /** - * @delayed_delete: Work item used when we can't delete the BO - * immediately - */ - struct work_struct delayed_delete; - - /** - * Special members that are protected by the reserve lock - * and the bo::lock when written to. Can be read with - * either of these locks held. - */ - - struct sg_table *sg; -}; - -/** - * struct ttm_bo_kmap_obj - * - * @virtual: The current kernel virtual address. - * @page: The page when kmap'ing a single page. - * @bo_kmap_type: Type of bo_kmap. - * - * Object describing a kernel mapping. Since a TTM bo may be located - * in various memory types with various caching policies, the - * mapping can either be an ioremap, a vmap, a kmap or part of a - * premapped region. - */ - -#define TTM_BO_MAP_IOMEM_MASK 0x80 -struct ttm_bo_kmap_obj { - void *virtual; - struct page *page; - enum { - ttm_bo_map_iomap = 1 | TTM_BO_MAP_IOMEM_MASK, - ttm_bo_map_vmap = 2, - ttm_bo_map_kmap = 3, - ttm_bo_map_premapped = 4 | TTM_BO_MAP_IOMEM_MASK, - } bo_kmap_type; - struct ttm_buffer_object *bo; -}; - -/** - * struct ttm_operation_ctx - * - * @interruptible: Sleep interruptible if sleeping. - * @no_wait_gpu: Return immediately if the GPU is busy. - * @gfp_retry_mayfail: Set the __GFP_RETRY_MAYFAIL when allocation pages. - * @allow_res_evict: Allow eviction of reserved BOs. Can be used when multiple - * BOs share the same reservation object. - * @force_alloc: Don't check the memory account during suspend or CPU page - * faults. Should only be used by TTM internally. - * @resv: Reservation object to allow reserved evictions with. - * - * Context for TTM operations like changing buffer placement or general memory - * allocation. - */ -struct ttm_operation_ctx { - bool interruptible; - bool no_wait_gpu; - bool gfp_retry_mayfail; - bool allow_res_evict; - bool force_alloc; - struct dma_resv *resv; - uint64_t bytes_moved; -}; - -/** - * ttm_bo_get - reference a struct ttm_buffer_object - * - * @bo: The buffer object. - */ -static inline void ttm_bo_get(struct ttm_buffer_object *bo) -{ - kref_get(&bo->kref); -} - -/** - * ttm_bo_get_unless_zero - reference a struct ttm_buffer_object unless - * its refcount has already reached zero. - * @bo: The buffer object. - * - * Used to reference a TTM buffer object in lookups where the object is removed - * from the lookup structure during the destructor and for RCU lookups. - * - * Returns: @bo if the referencing was successful, NULL otherwise. - */ -static inline __must_check struct ttm_buffer_object * -ttm_bo_get_unless_zero(struct ttm_buffer_object *bo) -{ - if (!kref_get_unless_zero(&bo->kref)) - return NULL; - return bo; -} - -/** - * ttm_bo_wait - wait for buffer idle. - * - * @bo: The buffer object. - * @interruptible: Use interruptible wait. - * @no_wait: Return immediately if buffer is busy. - * - * This function must be called with the bo::mutex held, and makes - * sure any previous rendering to the buffer is completed. - * Note: It might be necessary to block validations before the - * wait by reserving the buffer. - * Returns -EBUSY if no_wait is true and the buffer is busy. - * Returns -ERESTARTSYS if interrupted by a signal. - */ -int ttm_bo_wait(struct ttm_buffer_object *bo, bool interruptible, bool no_wait); - -static inline int ttm_bo_wait_ctx(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx) -{ - return ttm_bo_wait(bo, ctx->interruptible, ctx->no_wait_gpu); -} - -/** - * ttm_bo_validate - * - * @bo: The buffer object. - * @placement: Proposed placement for the buffer object. - * @ctx: validation parameters. - * - * Changes placement and caching policy of the buffer object - * according proposed placement. - * Returns - * -EINVAL on invalid proposed placement. - * -ENOMEM on out-of-memory condition. - * -EBUSY if no_wait is true and buffer busy. - * -ERESTARTSYS if interrupted by a signal. - */ -int ttm_bo_validate(struct ttm_buffer_object *bo, - struct ttm_placement *placement, - struct ttm_operation_ctx *ctx); - -/** - * ttm_bo_put - * - * @bo: The buffer object. - * - * Unreference a buffer object. - */ -void ttm_bo_put(struct ttm_buffer_object *bo); - -void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo); -void ttm_bo_set_bulk_move(struct ttm_buffer_object *bo, - struct ttm_lru_bulk_move *bulk); - -/** - * ttm_bo_eviction_valuable - * - * @bo: The buffer object to evict - * @place: the placement we need to make room for - * - * Check if it is valuable to evict the BO to make room for the given placement. - */ -bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, - const struct ttm_place *place); - -int ttm_bo_init_reserved(struct ttm_device *bdev, struct ttm_buffer_object *bo, - enum ttm_bo_type type, struct ttm_placement *placement, - uint32_t alignment, struct ttm_operation_ctx *ctx, - struct sg_table *sg, struct dma_resv *resv, - void (*destroy) (struct ttm_buffer_object *)); -int ttm_bo_init_validate(struct ttm_device *bdev, struct ttm_buffer_object *bo, - enum ttm_bo_type type, struct ttm_placement *placement, - uint32_t alignment, bool interruptible, - struct sg_table *sg, struct dma_resv *resv, - void (*destroy) (struct ttm_buffer_object *)); - -/** - * ttm_kmap_obj_virtual - * - * @map: A struct ttm_bo_kmap_obj returned from ttm_bo_kmap. - * @is_iomem: Pointer to an integer that on return indicates 1 if the - * virtual map is io memory, 0 if normal memory. - * - * Returns the virtual address of a buffer object area mapped by ttm_bo_kmap. - * If *is_iomem is 1 on return, the virtual address points to an io memory area, - * that should strictly be accessed by the iowriteXX() and similar functions. - */ -static inline void *ttm_kmap_obj_virtual(struct ttm_bo_kmap_obj *map, - bool *is_iomem) -{ - *is_iomem = !!(map->bo_kmap_type & TTM_BO_MAP_IOMEM_MASK); - return map->virtual; -} - -/** - * ttm_bo_kmap - * - * @bo: The buffer object. - * @start_page: The first page to map. - * @num_pages: Number of pages to map. - * @map: pointer to a struct ttm_bo_kmap_obj representing the map. - * - * Sets up a kernel virtual mapping, using ioremap, vmap or kmap to the - * data in the buffer object. The ttm_kmap_obj_virtual function can then be - * used to obtain a virtual address to the data. - * - * Returns - * -ENOMEM: Out of memory. - * -EINVAL: Invalid range. - */ -int ttm_bo_kmap(struct ttm_buffer_object *bo, unsigned long start_page, - unsigned long num_pages, struct ttm_bo_kmap_obj *map); - -/** - * ttm_bo_kunmap - * - * @map: Object describing the map to unmap. - * - * Unmaps a kernel map set up by ttm_bo_kmap. - */ -void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map); - -/** - * ttm_bo_vmap - * - * @bo: The buffer object. - * @map: pointer to a struct iosys_map representing the map. - * - * Sets up a kernel virtual mapping, using ioremap or vmap to the - * data in the buffer object. The parameter @map returns the virtual - * address as struct iosys_map. Unmap the buffer with ttm_bo_vunmap(). - * - * Returns - * -ENOMEM: Out of memory. - * -EINVAL: Invalid range. - */ -int ttm_bo_vmap(struct ttm_buffer_object *bo, struct iosys_map *map); - -/** - * ttm_bo_vunmap - * - * @bo: The buffer object. - * @map: Object describing the map to unmap. - * - * Unmaps a kernel map set up by ttm_bo_vmap(). - */ -void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct iosys_map *map); - -/** - * ttm_bo_mmap_obj - mmap memory backed by a ttm buffer object. - * - * @vma: vma as input from the fbdev mmap method. - * @bo: The bo backing the address space. - * - * Maps a buffer object. - */ -int ttm_bo_mmap_obj(struct vm_area_struct *vma, struct ttm_buffer_object *bo); - -/** - * ttm_bo_io - * - * @bdev: Pointer to the struct ttm_device. - * @filp: Pointer to the struct file attempting to read / write. - * @wbuf: User-space pointer to address of buffer to write. NULL on read. - * @rbuf: User-space pointer to address of buffer to read into. - * Null on write. - * @count: Number of bytes to read / write. - * @f_pos: Pointer to current file position. - * @write: 1 for read, 0 for write. - * - * This function implements read / write into ttm buffer objects, and is - * intended to - * be called from the fops::read and fops::write method. - * Returns: - * See man (2) write, man(2) read. In particular, - * the function may return -ERESTARTSYS if - * interrupted by a signal. - */ -ssize_t ttm_bo_io(struct ttm_device *bdev, struct file *filp, - const char __user *wbuf, char __user *rbuf, - size_t count, loff_t *f_pos, bool write); - -int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, - gfp_t gfp_flags); - -void ttm_bo_pin(struct ttm_buffer_object *bo); -void ttm_bo_unpin(struct ttm_buffer_object *bo); - -int ttm_mem_evict_first(struct ttm_device *bdev, - struct ttm_resource_manager *man, - const struct ttm_place *place, - struct ttm_operation_ctx *ctx, - struct ww_acquire_ctx *ticket); - -/* Default number of pre-faulted pages in the TTM fault handler */ -#define TTM_BO_VM_NUM_PREFAULT 16 - -vm_fault_t ttm_bo_vm_reserve(struct ttm_buffer_object *bo, - struct vm_fault *vmf); - -vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, - pgprot_t prot, - pgoff_t num_prefault); - -vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf); - -void ttm_bo_vm_open(struct vm_area_struct *vma); - -void ttm_bo_vm_close(struct vm_area_struct *vma); - -int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr, - void *buf, int len, int write); -vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot); - -#endif diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h deleted file mode 100644 index 1afa891f488a..000000000000 --- a/include/drm/ttm/ttm_bo_driver.h +++ /dev/null @@ -1,303 +0,0 @@ -/************************************************************************** - * - * Copyright (c) 2006-2009 Vmware, Inc., Palo Alto, CA., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ -/* - * Authors: Thomas Hellstrom - */ -#ifndef _TTM_BO_DRIVER_H_ -#define _TTM_BO_DRIVER_H_ - -#include -#include -#include -#include -#include -#include - -#include - -#include "ttm_bo_api.h" -#include "ttm_kmap_iter.h" -#include "ttm_placement.h" -#include "ttm_tt.h" -#include "ttm_pool.h" - -/* - * ttm_bo.c - */ - -/** - * ttm_bo_mem_space - * - * @bo: Pointer to a struct ttm_buffer_object. the data of which - * we want to allocate space for. - * @proposed_placement: Proposed new placement for the buffer object. - * @mem: A struct ttm_resource. - * @interruptible: Sleep interruptible when sliping. - * @no_wait_gpu: Return immediately if the GPU is busy. - * - * Allocate memory space for the buffer object pointed to by @bo, using - * the placement flags in @mem, potentially evicting other idle buffer objects. - * This function may sleep while waiting for space to become available. - * Returns: - * -EBUSY: No space available (only if no_wait == 1). - * -ENOMEM: Could not allocate memory for the buffer object, either due to - * fragmentation or concurrent allocators. - * -ERESTARTSYS: An interruptible sleep was interrupted by a signal. - */ -int ttm_bo_mem_space(struct ttm_buffer_object *bo, - struct ttm_placement *placement, - struct ttm_resource **mem, - struct ttm_operation_ctx *ctx); - -/** - * ttm_bo_unmap_virtual - * - * @bo: tear down the virtual mappings for this BO - */ -void ttm_bo_unmap_virtual(struct ttm_buffer_object *bo); - -/** - * ttm_bo_reserve: - * - * @bo: A pointer to a struct ttm_buffer_object. - * @interruptible: Sleep interruptible if waiting. - * @no_wait: Don't sleep while trying to reserve, rather return -EBUSY. - * @ticket: ticket used to acquire the ww_mutex. - * - * Locks a buffer object for validation. (Or prevents other processes from - * locking it for validation), while taking a number of measures to prevent - * deadlocks. - * - * Returns: - * -EDEADLK: The reservation may cause a deadlock. - * Release all buffer reservations, wait for @bo to become unreserved and - * try again. - * -ERESTARTSYS: A wait for the buffer to become unreserved was interrupted by - * a signal. Release all buffer reservations and return to user-space. - * -EBUSY: The function needed to sleep, but @no_wait was true - * -EALREADY: Bo already reserved using @ticket. This error code will only - * be returned if @use_ticket is set to true. - */ -static inline int ttm_bo_reserve(struct ttm_buffer_object *bo, - bool interruptible, bool no_wait, - struct ww_acquire_ctx *ticket) -{ - int ret; - - if (no_wait) { - bool success; - if (WARN_ON(ticket)) - return -EBUSY; - - success = dma_resv_trylock(bo->base.resv); - return success ? 0 : -EBUSY; - } - - if (interruptible) - ret = dma_resv_lock_interruptible(bo->base.resv, ticket); - else - ret = dma_resv_lock(bo->base.resv, ticket); - if (ret == -EINTR) - return -ERESTARTSYS; - return ret; -} - -/** - * ttm_bo_reserve_slowpath: - * @bo: A pointer to a struct ttm_buffer_object. - * @interruptible: Sleep interruptible if waiting. - * @sequence: Set (@bo)->sequence to this value after lock - * - * This is called after ttm_bo_reserve returns -EAGAIN and we backed off - * from all our other reservations. Because there are no other reservations - * held by us, this function cannot deadlock any more. - */ -static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, - bool interruptible, - struct ww_acquire_ctx *ticket) -{ - if (interruptible) { - int ret = dma_resv_lock_slow_interruptible(bo->base.resv, - ticket); - if (ret == -EINTR) - ret = -ERESTARTSYS; - return ret; - } - dma_resv_lock_slow(bo->base.resv, ticket); - return 0; -} - -static inline void -ttm_bo_move_to_lru_tail_unlocked(struct ttm_buffer_object *bo) -{ - spin_lock(&bo->bdev->lru_lock); - ttm_bo_move_to_lru_tail(bo); - spin_unlock(&bo->bdev->lru_lock); -} - -static inline void ttm_bo_assign_mem(struct ttm_buffer_object *bo, - struct ttm_resource *new_mem) -{ - WARN_ON(bo->resource); - bo->resource = new_mem; -} - -/** - * ttm_bo_move_null = assign memory for a buffer object. - * @bo: The bo to assign the memory to - * @new_mem: The memory to be assigned. - * - * Assign the memory from new_mem to the memory of the buffer object bo. - */ -static inline void ttm_bo_move_null(struct ttm_buffer_object *bo, - struct ttm_resource *new_mem) -{ - ttm_resource_free(bo, &bo->resource); - ttm_bo_assign_mem(bo, new_mem); -} - -/** - * ttm_bo_unreserve - * - * @bo: A pointer to a struct ttm_buffer_object. - * - * Unreserve a previous reservation of @bo. - */ -static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) -{ - ttm_bo_move_to_lru_tail_unlocked(bo); - dma_resv_unlock(bo->base.resv); -} - -/* - * ttm_bo_util.c - */ -int ttm_mem_io_reserve(struct ttm_device *bdev, - struct ttm_resource *mem); -void ttm_mem_io_free(struct ttm_device *bdev, - struct ttm_resource *mem); - -/** - * ttm_bo_move_memcpy - * - * @bo: A pointer to a struct ttm_buffer_object. - * @interruptible: Sleep interruptible if waiting. - * @no_wait_gpu: Return immediately if the GPU is busy. - * @new_mem: struct ttm_resource indicating where to move. - * - * Fallback move function for a mappable buffer object in mappable memory. - * The function will, if successful, - * free any old aperture space, and set (@new_mem)->mm_node to NULL, - * and update the (@bo)->mem placement flags. If unsuccessful, the old - * data remains untouched, and it's up to the caller to free the - * memory space indicated by @new_mem. - * Returns: - * !0: Failure. - */ - -int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, - struct ttm_operation_ctx *ctx, - struct ttm_resource *new_mem); - -/** - * ttm_bo_move_accel_cleanup. - * - * @bo: A pointer to a struct ttm_buffer_object. - * @fence: A fence object that signals when moving is complete. - * @evict: This is an evict move. Don't return until the buffer is idle. - * @pipeline: evictions are to be pipelined. - * @new_mem: struct ttm_resource indicating where to move. - * - * Accelerated move function to be called when an accelerated move - * has been scheduled. The function will create a new temporary buffer object - * representing the old placement, and put the sync object on both buffer - * objects. After that the newly created buffer object is unref'd to be - * destroyed when the move is complete. This will help pipeline - * buffer moves. - */ -int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, - struct dma_fence *fence, bool evict, - bool pipeline, - struct ttm_resource *new_mem); - -/** - * ttm_bo_move_sync_cleanup. - * - * @bo: A pointer to a struct ttm_buffer_object. - * @new_mem: struct ttm_resource indicating where to move. - * - * Special case of ttm_bo_move_accel_cleanup where the bo is guaranteed - * by the caller to be idle. Typically used after memcpy buffer moves. - */ -void ttm_bo_move_sync_cleanup(struct ttm_buffer_object *bo, - struct ttm_resource *new_mem); - -/** - * ttm_bo_pipeline_gutting. - * - * @bo: A pointer to a struct ttm_buffer_object. - * - * Pipelined gutting a BO of its backing store. - */ -int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo); - -/** - * ttm_io_prot - * - * bo: ttm buffer object - * res: ttm resource object - * @tmp: Page protection flag for a normal, cached mapping. - * - * Utility function that returns the pgprot_t that should be used for - * setting up a PTE with the caching model indicated by @c_state. - */ -pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res, - pgprot_t tmp); - -/** - * ttm_bo_tt_bind - * - * Bind the object tt to a memory resource. - */ -int ttm_bo_tt_bind(struct ttm_buffer_object *bo, struct ttm_resource *mem); - -/** - * ttm_bo_tt_destroy. - */ -void ttm_bo_tt_destroy(struct ttm_buffer_object *bo); - -void ttm_move_memcpy(bool clear, - u32 num_pages, - struct ttm_kmap_iter *dst_iter, - struct ttm_kmap_iter *src_iter); - -struct ttm_kmap_iter * -ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io, - struct io_mapping *iomap, - struct sg_table *st, - resource_size_t start); -#endif diff --git a/include/drm/ttm/ttm_execbuf_util.h b/include/drm/ttm/ttm_execbuf_util.h index a99d7fdf2964..03aca29d3ce4 100644 --- a/include/drm/ttm/ttm_execbuf_util.h +++ b/include/drm/ttm/ttm_execbuf_util.h @@ -33,7 +33,9 @@ #include -#include "ttm_bo_api.h" +struct ww_acquire_ctx; +struct dma_fence; +struct ttm_buffer_object; /** * struct ttm_validate_buffer -- cgit v1.2.3 From 0c3627c744068fe95b235c9aa25d2bd56bde7e55 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 1 Dec 2022 16:11:32 +0100 Subject: drm/tests: helpers: Move the helper header to include/drm We'll need to use those helpers from drivers too, so let's move it to a more visible location. Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20221123-rpi-kunit-tests-v3-1-4615a663a84a@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_client_modeset_test.c | 3 +-- drivers/gpu/drm/tests/drm_kunit_helpers.c | 3 +-- drivers/gpu/drm/tests/drm_kunit_helpers.h | 11 ----------- drivers/gpu/drm/tests/drm_modes_test.c | 3 +-- drivers/gpu/drm/tests/drm_probe_helper_test.c | 3 +-- include/drm/drm_kunit_helpers.h | 11 +++++++++++ 6 files changed, 15 insertions(+), 19 deletions(-) delete mode 100644 drivers/gpu/drm/tests/drm_kunit_helpers.h create mode 100644 include/drm/drm_kunit_helpers.h (limited to 'include') diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c index 52929536a158..ed2f62e92fea 100644 --- a/drivers/gpu/drm/tests/drm_client_modeset_test.c +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c @@ -8,12 +8,11 @@ #include #include #include +#include #include #include #include -#include "drm_kunit_helpers.h" - struct drm_client_modeset_test_priv { struct drm_device *drm; struct drm_connector connector; diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 8c738384a992..6600a4db3158 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -1,14 +1,13 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include #include #include #include -#include "drm_kunit_helpers.h" - struct kunit_dev { struct drm_device base; }; diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.h b/drivers/gpu/drm/tests/drm_kunit_helpers.h deleted file mode 100644 index 20ab6eec4c89..000000000000 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.h +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -#ifndef DRM_KUNIT_HELPERS_H_ -#define DRM_KUNIT_HELPERS_H_ - -struct drm_device; -struct kunit; - -struct drm_device *drm_kunit_device_init(struct kunit *test, u32 features, char *name); - -#endif // DRM_KUNIT_HELPERS_H_ diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c index 9358a885c58b..3953e478c4d0 100644 --- a/drivers/gpu/drm/tests/drm_modes_test.c +++ b/drivers/gpu/drm/tests/drm_modes_test.c @@ -4,14 +4,13 @@ */ #include +#include #include #include #include -#include "drm_kunit_helpers.h" - struct drm_test_modes_priv { struct drm_device *drm; }; diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c index 211131405500..6b3b7d0f948e 100644 --- a/drivers/gpu/drm/tests/drm_probe_helper_test.c +++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,8 +15,6 @@ #include -#include "drm_kunit_helpers.h" - struct drm_probe_helper_test_priv { struct drm_device *drm; struct drm_connector connector; diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h new file mode 100644 index 000000000000..20ab6eec4c89 --- /dev/null +++ b/include/drm/drm_kunit_helpers.h @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef DRM_KUNIT_HELPERS_H_ +#define DRM_KUNIT_HELPERS_H_ + +struct drm_device; +struct kunit; + +struct drm_device *drm_kunit_device_init(struct kunit *test, u32 features, char *name); + +#endif // DRM_KUNIT_HELPERS_H_ -- cgit v1.2.3 From 83ee69a89f32d60669e66dad1c5d841573e5a8ec Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 1 Dec 2022 16:11:36 +0100 Subject: drm/tests: helpers: Rename the device init helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The name doesn't really fit the conventions for the other helpers in DRM/KMS, so let's rename it to make it obvious that we allocate a new DRM device. Reviewed-by: Maíra Canal Link: https://lore.kernel.org/r/20221123-rpi-kunit-tests-v3-5-4615a663a84a@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_client_modeset_test.c | 3 ++- drivers/gpu/drm/tests/drm_kunit_helpers.c | 8 +++++--- drivers/gpu/drm/tests/drm_modes_test.c | 3 ++- drivers/gpu/drm/tests/drm_probe_helper_test.c | 5 +++-- include/drm/drm_kunit_helpers.h | 5 ++++- 5 files changed, 16 insertions(+), 8 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c index ed2f62e92fea..6cdf08f582ce 100644 --- a/drivers/gpu/drm/tests/drm_client_modeset_test.c +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c @@ -59,7 +59,8 @@ static int drm_client_modeset_test_init(struct kunit *test) test->priv = priv; - priv->drm = drm_kunit_device_init(test, DRIVER_MODESET, "drm-client-modeset-test"); + priv->drm = drm_kunit_helper_alloc_drm_device(test, DRIVER_MODESET, + "drm-client-modeset-test"); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); ret = drmm_connector_init(priv->drm, &priv->connector, diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 4fe131141718..e718073ba6e9 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -36,7 +36,7 @@ static void dev_free(struct kunit_resource *res) } /** - * drm_kunit_device_init - Allocates a mock DRM device for KUnit tests + * drm_kunit_helper_alloc_drm_device - Allocates a mock DRM device for KUnit tests * @test: The test context object * @features: Mocked DRM device driver features * @name: Name of the struct &device to allocate @@ -52,7 +52,9 @@ static void dev_free(struct kunit_resource *res) * Returns: * A pointer to the new drm_device, or an ERR_PTR() otherwise. */ -struct drm_device *drm_kunit_device_init(struct kunit *test, u32 features, char *name) +struct drm_device * +drm_kunit_helper_alloc_drm_device(struct kunit *test, + u32 features, char *name) { struct kunit_dev *kdev; struct drm_device *drm; @@ -82,7 +84,7 @@ struct drm_device *drm_kunit_device_init(struct kunit *test, u32 features, char return drm; } -EXPORT_SYMBOL_GPL(drm_kunit_device_init); +EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_drm_device); MODULE_AUTHOR("Maxime Ripard "); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c index 3953e478c4d0..6723089dff9f 100644 --- a/drivers/gpu/drm/tests/drm_modes_test.c +++ b/drivers/gpu/drm/tests/drm_modes_test.c @@ -22,7 +22,8 @@ static int drm_test_modes_init(struct kunit *test) priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, priv); - priv->drm = drm_kunit_device_init(test, DRIVER_MODESET, "drm-modes-test"); + priv->drm = drm_kunit_helper_alloc_drm_device(test, DRIVER_MODESET, + "drm-modes-test"); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); test->priv = priv; diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c index 6b3b7d0f948e..b44768100ed5 100644 --- a/drivers/gpu/drm/tests/drm_probe_helper_test.c +++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c @@ -39,8 +39,9 @@ static int drm_probe_helper_test_init(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, priv); test->priv = priv; - priv->drm = drm_kunit_device_init(test, DRIVER_MODESET | DRIVER_ATOMIC, - "drm-probe-helper-test"); + priv->drm = drm_kunit_helper_alloc_drm_device(test, + DRIVER_MODESET | DRIVER_ATOMIC, + "drm-probe-helper-test"); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); connector = &priv->connector; diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index 20ab6eec4c89..e9870c7911fe 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -6,6 +6,9 @@ struct drm_device; struct kunit; -struct drm_device *drm_kunit_device_init(struct kunit *test, u32 features, char *name); +struct drm_device * +drm_kunit_helper_alloc_drm_device(struct kunit *test, + u32 features, + char *name); #endif // DRM_KUNIT_HELPERS_H_ -- cgit v1.2.3 From 1d041a469e5de3d9d1b208e12af9265882dcd221 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 1 Dec 2022 16:11:37 +0100 Subject: drm/tests: helpers: Remove the name parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device name isn't really useful, we can just define it instead of exposing it in the API. Reviewed-by: Maíra Canal Link: https://lore.kernel.org/r/20221123-rpi-kunit-tests-v3-6-4615a663a84a@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_client_modeset_test.c | 3 +-- drivers/gpu/drm/tests/drm_kunit_helpers.c | 7 ++++--- drivers/gpu/drm/tests/drm_modes_test.c | 3 +-- drivers/gpu/drm/tests/drm_probe_helper_test.c | 3 +-- include/drm/drm_kunit_helpers.h | 3 +-- 5 files changed, 8 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c index 6cdf08f582ce..4d475ae6dbb6 100644 --- a/drivers/gpu/drm/tests/drm_client_modeset_test.c +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c @@ -59,8 +59,7 @@ static int drm_client_modeset_test_init(struct kunit *test) test->priv = priv; - priv->drm = drm_kunit_helper_alloc_drm_device(test, DRIVER_MODESET, - "drm-client-modeset-test"); + priv->drm = drm_kunit_helper_alloc_drm_device(test, DRIVER_MODESET); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); ret = drmm_connector_init(priv->drm, &priv->connector, diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index e718073ba6e9..ec33fcbd092d 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -8,6 +8,8 @@ #include +#define KUNIT_DEVICE_NAME "drm-kunit-mock-device" + struct kunit_dev { struct drm_device base; }; @@ -39,7 +41,6 @@ static void dev_free(struct kunit_resource *res) * drm_kunit_helper_alloc_drm_device - Allocates a mock DRM device for KUnit tests * @test: The test context object * @features: Mocked DRM device driver features - * @name: Name of the struct &device to allocate * * This function allocates a new struct &device, creates a struct * &drm_driver and will create a struct &drm_device using both. @@ -54,7 +55,7 @@ static void dev_free(struct kunit_resource *res) */ struct drm_device * drm_kunit_helper_alloc_drm_device(struct kunit *test, - u32 features, char *name) + u32 features) { struct kunit_dev *kdev; struct drm_device *drm; @@ -62,7 +63,7 @@ drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev; int ret; - dev = kunit_alloc_resource(test, dev_init, dev_free, GFP_KERNEL, name); + dev = kunit_alloc_resource(test, dev_init, dev_free, GFP_KERNEL, KUNIT_DEVICE_NAME); if (!dev) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c index 6723089dff9f..35965ad86188 100644 --- a/drivers/gpu/drm/tests/drm_modes_test.c +++ b/drivers/gpu/drm/tests/drm_modes_test.c @@ -22,8 +22,7 @@ static int drm_test_modes_init(struct kunit *test) priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, priv); - priv->drm = drm_kunit_helper_alloc_drm_device(test, DRIVER_MODESET, - "drm-modes-test"); + priv->drm = drm_kunit_helper_alloc_drm_device(test, DRIVER_MODESET); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); test->priv = priv; diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c index b44768100ed5..86ea988e14be 100644 --- a/drivers/gpu/drm/tests/drm_probe_helper_test.c +++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c @@ -40,8 +40,7 @@ static int drm_probe_helper_test_init(struct kunit *test) test->priv = priv; priv->drm = drm_kunit_helper_alloc_drm_device(test, - DRIVER_MODESET | DRIVER_ATOMIC, - "drm-probe-helper-test"); + DRIVER_MODESET | DRIVER_ATOMIC); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); connector = &priv->connector; diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index e9870c7911fe..6c12b1426ba0 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -8,7 +8,6 @@ struct kunit; struct drm_device * drm_kunit_helper_alloc_drm_device(struct kunit *test, - u32 features, - char *name); + u32 features); #endif // DRM_KUNIT_HELPERS_H_ -- cgit v1.2.3 From 9ecd8045bf64f8f277acea4bf35c14b369529f09 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 1 Dec 2022 16:11:38 +0100 Subject: drm/tests: helpers: Create the device in another function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll need in some tests to control when the device needs to be added and removed, so let's split the device creation from the DRM device creation function. Reviewed-by: Maíra Canal Link: https://lore.kernel.org/r/20221123-rpi-kunit-tests-v3-7-4615a663a84a@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_client_modeset_test.c | 14 ++++++- drivers/gpu/drm/tests/drm_kunit_helpers.c | 56 +++++++++++++++---------- drivers/gpu/drm/tests/drm_modes_test.c | 15 ++++++- drivers/gpu/drm/tests/drm_probe_helper_test.c | 14 ++++++- include/drm/drm_kunit_helpers.h | 5 ++- 5 files changed, 77 insertions(+), 27 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c index 4d475ae6dbb6..053dbc0106d9 100644 --- a/drivers/gpu/drm/tests/drm_client_modeset_test.c +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c @@ -15,6 +15,7 @@ struct drm_client_modeset_test_priv { struct drm_device *drm; + struct device *dev; struct drm_connector connector; }; @@ -59,7 +60,10 @@ static int drm_client_modeset_test_init(struct kunit *test) test->priv = priv; - priv->drm = drm_kunit_helper_alloc_drm_device(test, DRIVER_MODESET); + priv->dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); + + priv->drm = drm_kunit_helper_alloc_drm_device(test, priv->dev, DRIVER_MODESET); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); ret = drmm_connector_init(priv->drm, &priv->connector, @@ -76,6 +80,13 @@ static int drm_client_modeset_test_init(struct kunit *test) return 0; } +static void drm_client_modeset_test_exit(struct kunit *test) +{ + struct drm_client_modeset_test_priv *priv = test->priv; + + drm_kunit_helper_free_device(test, priv->dev); +} + static void drm_test_pick_cmdline_res_1920_1080_60(struct kunit *test) { struct drm_client_modeset_test_priv *priv = test->priv; @@ -175,6 +186,7 @@ static struct kunit_case drm_test_pick_cmdline_tests[] = { static struct kunit_suite drm_test_pick_cmdline_test_suite = { .name = "drm_test_pick_cmdline", .init = drm_client_modeset_test_init, + .exit = drm_client_modeset_test_exit, .test_cases = drm_test_pick_cmdline_tests }; diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index ec33fcbd092d..4bf98bd0a8c6 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -17,36 +17,51 @@ struct kunit_dev { static const struct drm_mode_config_funcs drm_mode_config_funcs = { }; -static int dev_init(struct kunit_resource *res, void *ptr) +/** + * drm_kunit_helper_alloc_device - Allocate a mock device for a KUnit test + * @test: The test context object + * + * This allocates a fake struct &device to create a mock for a KUnit + * test. + * + * Callers need to make sure drm_kunit_helper_free_device() on the + * device when done. + * + * Returns: + * A pointer to the new device, or an ERR_PTR() otherwise. + */ +struct device *drm_kunit_helper_alloc_device(struct kunit *test) { - char *name = ptr; - struct device *dev; - - dev = root_device_register(name); - if (IS_ERR(dev)) - return PTR_ERR(dev); - - res->data = dev; - return 0; + return root_device_register(KUNIT_DEVICE_NAME); } +EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_device); -static void dev_free(struct kunit_resource *res) +/** + * drm_kunit_helper_free_device - Frees a mock device + * @test: The test context object + * @dev: The device to free + * + * Frees a device allocated with drm_kunit_helper_alloc_device(). + */ +void drm_kunit_helper_free_device(struct kunit *test, struct device *dev) { - struct device *dev = res->data; - root_device_unregister(dev); } +EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device); /** * drm_kunit_helper_alloc_drm_device - Allocates a mock DRM device for KUnit tests * @test: The test context object + * @dev: The parent device object * @features: Mocked DRM device driver features * - * This function allocates a new struct &device, creates a struct - * &drm_driver and will create a struct &drm_device using both. + * This function creates a struct &drm_driver and will create a struct + * &drm_device from @dev and that driver. + * + * @dev should be allocated using drm_kunit_helper_alloc_device(). * - * The device and driver are tied to the @test context and will get - * cleaned at the end of the test. The drm_device is allocated through + * The driver is tied to the @test context and will get cleaned at the + * end of the test. The drm_device is allocated through * devm_drm_dev_alloc() and will thus be freed through a device-managed * resource. * @@ -54,19 +69,14 @@ static void dev_free(struct kunit_resource *res) * A pointer to the new drm_device, or an ERR_PTR() otherwise. */ struct drm_device * -drm_kunit_helper_alloc_drm_device(struct kunit *test, +drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, u32 features) { struct kunit_dev *kdev; struct drm_device *drm; struct drm_driver *driver; - struct device *dev; int ret; - dev = kunit_alloc_resource(test, dev_init, dev_free, GFP_KERNEL, KUNIT_DEVICE_NAME); - if (!dev) - return ERR_PTR(-ENOMEM); - driver = kunit_kzalloc(test, sizeof(*driver), GFP_KERNEL); if (!driver) return ERR_PTR(-ENOMEM); diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c index 35965ad86188..d1e9f3c0433a 100644 --- a/drivers/gpu/drm/tests/drm_modes_test.c +++ b/drivers/gpu/drm/tests/drm_modes_test.c @@ -13,6 +13,7 @@ struct drm_test_modes_priv { struct drm_device *drm; + struct device *dev; }; static int drm_test_modes_init(struct kunit *test) @@ -22,7 +23,11 @@ static int drm_test_modes_init(struct kunit *test) priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); KUNIT_ASSERT_NOT_NULL(test, priv); - priv->drm = drm_kunit_helper_alloc_drm_device(test, DRIVER_MODESET); + priv->dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); + + priv->drm = drm_kunit_helper_alloc_drm_device(test, priv->dev, + DRIVER_MODESET); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); test->priv = priv; @@ -30,6 +35,13 @@ static int drm_test_modes_init(struct kunit *test) return 0; } +static void drm_test_modes_exit(struct kunit *test) +{ + struct drm_test_modes_priv *priv = test->priv; + + drm_kunit_helper_free_device(test, priv->dev); +} + static void drm_test_modes_analog_tv_ntsc_480i(struct kunit *test) { struct drm_test_modes_priv *priv = test->priv; @@ -135,6 +147,7 @@ static struct kunit_case drm_modes_analog_tv_tests[] = { static struct kunit_suite drm_modes_analog_tv_test_suite = { .name = "drm_modes_analog_tv", .init = drm_test_modes_init, + .exit = drm_test_modes_exit, .test_cases = drm_modes_analog_tv_tests, }; diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c index 86ea988e14be..bfca61c6099d 100644 --- a/drivers/gpu/drm/tests/drm_probe_helper_test.c +++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c @@ -17,6 +17,7 @@ struct drm_probe_helper_test_priv { struct drm_device *drm; + struct device *dev; struct drm_connector connector; }; @@ -39,7 +40,10 @@ static int drm_probe_helper_test_init(struct kunit *test) KUNIT_ASSERT_NOT_NULL(test, priv); test->priv = priv; - priv->drm = drm_kunit_helper_alloc_drm_device(test, + priv->dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); + + priv->drm = drm_kunit_helper_alloc_drm_device(test, priv->dev, DRIVER_MODESET | DRIVER_ATOMIC); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); @@ -55,6 +59,13 @@ static int drm_probe_helper_test_init(struct kunit *test) return 0; } +static void drm_probe_helper_test_exit(struct kunit *test) +{ + struct drm_probe_helper_test_priv *priv = test->priv; + + drm_kunit_helper_free_device(test, priv->dev); +} + typedef struct drm_display_mode *(*expected_mode_func_t)(struct drm_device *); struct drm_connector_helper_tv_get_modes_test { @@ -196,6 +207,7 @@ static struct kunit_case drm_test_connector_helper_tv_get_modes_tests[] = { static struct kunit_suite drm_test_connector_helper_tv_get_modes_suite = { .name = "drm_connector_helper_tv_get_modes", .init = drm_probe_helper_test_init, + .exit = drm_probe_helper_test_exit, .test_cases = drm_test_connector_helper_tv_get_modes_tests, }; diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index 6c12b1426ba0..b4277fe92c38 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -6,8 +6,11 @@ struct drm_device; struct kunit; +struct device *drm_kunit_helper_alloc_device(struct kunit *test); +void drm_kunit_helper_free_device(struct kunit *test, struct device *dev); + struct drm_device * -drm_kunit_helper_alloc_drm_device(struct kunit *test, +drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, u32 features); #endif // DRM_KUNIT_HELPERS_H_ -- cgit v1.2.3 From a9143c5852a7a13d60ef685d27f9617f2a52338b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 1 Dec 2022 16:11:41 +0100 Subject: drm/tests: helpers: Allow for a custom device struct to be allocated The current helper to allocate a DRM device doesn't allow for any subclassing by drivers, which is going to be troublesome as we work on getting some kunit testing on atomic modesetting code. Let's use a similar pattern to the other allocation helpers by providing the structure size and offset as arguments. Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20221123-rpi-kunit-tests-v3-10-4615a663a84a@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_client_modeset_test.c | 4 ++- drivers/gpu/drm/tests/drm_kunit_helpers.c | 40 ++++++------------------- drivers/gpu/drm/tests/drm_modes_test.c | 5 ++-- drivers/gpu/drm/tests/drm_probe_helper_test.c | 5 ++-- include/drm/drm_kunit_helpers.h | 32 ++++++++++++++++++-- 5 files changed, 48 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c index 053dbc0106d9..416a279b6dae 100644 --- a/drivers/gpu/drm/tests/drm_client_modeset_test.c +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c @@ -63,7 +63,9 @@ static int drm_client_modeset_test_init(struct kunit *test) priv->dev = drm_kunit_helper_alloc_device(test); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); - priv->drm = drm_kunit_helper_alloc_drm_device(test, priv->dev, DRIVER_MODESET); + priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev, + sizeof(*priv->drm), 0, + DRIVER_MODESET); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); ret = drmm_connector_init(priv->drm, &priv->connector, diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 9bfd3cb9cde1..b5485ab8fbf9 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -11,10 +11,6 @@ #define KUNIT_DEVICE_NAME "drm-kunit-mock-device" -struct kunit_dev { - struct drm_device base; -}; - static const struct drm_mode_config_funcs drm_mode_config_funcs = { }; @@ -85,32 +81,14 @@ void drm_kunit_helper_free_device(struct kunit *test, struct device *dev) } EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device); -/** - * drm_kunit_helper_alloc_drm_device - Allocates a mock DRM device for KUnit tests - * @test: The test context object - * @dev: The parent device object - * @features: Mocked DRM device driver features - * - * This function creates a struct &drm_driver and will create a struct - * &drm_device from @dev and that driver. - * - * @dev should be allocated using drm_kunit_helper_alloc_device(). - * - * The driver is tied to the @test context and will get cleaned at the - * end of the test. The drm_device is allocated through - * devm_drm_dev_alloc() and will thus be freed through a device-managed - * resource. - * - * Returns: - * A pointer to the new drm_device, or an ERR_PTR() otherwise. - */ struct drm_device * -drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, - u32 features) +__drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, + size_t size, size_t offset, + u32 features) { - struct kunit_dev *kdev; struct drm_device *drm; struct drm_driver *driver; + void *container; int ret; driver = kunit_kzalloc(test, sizeof(*driver), GFP_KERNEL); @@ -118,11 +96,11 @@ drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, return ERR_PTR(-ENOMEM); driver->driver_features = features; - kdev = devm_drm_dev_alloc(dev, driver, struct kunit_dev, base); - if (IS_ERR(kdev)) - return ERR_CAST(kdev); + container = __devm_drm_dev_alloc(dev, driver, size, offset); + if (IS_ERR(container)) + return ERR_CAST(container); - drm = &kdev->base; + drm = container + offset; drm->mode_config.funcs = &drm_mode_config_funcs; ret = drmm_mode_config_init(drm); @@ -131,7 +109,7 @@ drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, return drm; } -EXPORT_SYMBOL_GPL(drm_kunit_helper_alloc_drm_device); +EXPORT_SYMBOL_GPL(__drm_kunit_helper_alloc_drm_device); MODULE_AUTHOR("Maxime Ripard "); MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tests/drm_modes_test.c b/drivers/gpu/drm/tests/drm_modes_test.c index d1e9f3c0433a..bc4aa2ce78be 100644 --- a/drivers/gpu/drm/tests/drm_modes_test.c +++ b/drivers/gpu/drm/tests/drm_modes_test.c @@ -26,8 +26,9 @@ static int drm_test_modes_init(struct kunit *test) priv->dev = drm_kunit_helper_alloc_device(test); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); - priv->drm = drm_kunit_helper_alloc_drm_device(test, priv->dev, - DRIVER_MODESET); + priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev, + sizeof(*priv->drm), 0, + DRIVER_MODESET); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); test->priv = priv; diff --git a/drivers/gpu/drm/tests/drm_probe_helper_test.c b/drivers/gpu/drm/tests/drm_probe_helper_test.c index bfca61c6099d..0ee65828623e 100644 --- a/drivers/gpu/drm/tests/drm_probe_helper_test.c +++ b/drivers/gpu/drm/tests/drm_probe_helper_test.c @@ -43,8 +43,9 @@ static int drm_probe_helper_test_init(struct kunit *test) priv->dev = drm_kunit_helper_alloc_device(test); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); - priv->drm = drm_kunit_helper_alloc_drm_device(test, priv->dev, - DRIVER_MODESET | DRIVER_ATOMIC); + priv->drm = __drm_kunit_helper_alloc_drm_device(test, priv->dev, + sizeof(*priv->drm), 0, + DRIVER_MODESET | DRIVER_ATOMIC); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm); connector = &priv->connector; diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index b4277fe92c38..df99fda95e89 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -10,7 +10,35 @@ struct device *drm_kunit_helper_alloc_device(struct kunit *test); void drm_kunit_helper_free_device(struct kunit *test, struct device *dev); struct drm_device * -drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, - u32 features); +__drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, + size_t size, size_t offset, + u32 features); + +/** + * drm_kunit_helper_alloc_drm_device - Allocates a mock DRM device for KUnit tests + * @_test: The test context object + * @_dev: The parent device object + * @_type: the type of the struct which contains struct &drm_device + * @_member: the name of the &drm_device within @_type. + * @_features: Mocked DRM device driver features + * + * This function creates a struct &drm_driver and will create a struct + * &drm_device from @_dev and that driver. + * + * @_dev should be allocated using drm_kunit_helper_alloc_device(). + * + * The driver is tied to the @_test context and will get cleaned at the + * end of the test. The drm_device is allocated through + * devm_drm_dev_alloc() and will thus be freed through a device-managed + * resource. + * + * Returns: + * A pointer to the new drm_device, or an ERR_PTR() otherwise. + */ +#define drm_kunit_helper_alloc_drm_device(_test, _dev, _type, _member, _feat) \ + ((_type *)__drm_kunit_helper_alloc_drm_device(_test, _dev, \ + sizeof(_type), \ + offsetof(_type, _member), \ + _feat)) #endif // DRM_KUNIT_HELPERS_H_ -- cgit v1.2.3 From d98780310719bf4076d975c2ff65c44c7c0d929e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 1 Dec 2022 16:11:42 +0100 Subject: drm/tests: helpers: Allow to pass a custom drm_driver Some tests will need to provide their own drm_driver instead of relying on the dumb one in the helpers, so let's create a helper that allows to do so. Reviewed-by: Javier Martinez Canillas Link: https://lore.kernel.org/r/20221123-rpi-kunit-tests-v3-11-4615a663a84a@cerno.tech Signed-off-by: Maxime Ripard --- drivers/gpu/drm/tests/drm_kunit_helpers.c | 15 +++------ include/drm/drm_kunit_helpers.h | 51 +++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index b5485ab8fbf9..e98b4150f556 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -82,20 +82,15 @@ void drm_kunit_helper_free_device(struct kunit *test, struct device *dev) EXPORT_SYMBOL_GPL(drm_kunit_helper_free_device); struct drm_device * -__drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, - size_t size, size_t offset, - u32 features) +__drm_kunit_helper_alloc_drm_device_with_driver(struct kunit *test, + struct device *dev, + size_t size, size_t offset, + const struct drm_driver *driver) { struct drm_device *drm; - struct drm_driver *driver; void *container; int ret; - driver = kunit_kzalloc(test, sizeof(*driver), GFP_KERNEL); - if (!driver) - return ERR_PTR(-ENOMEM); - - driver->driver_features = features; container = __devm_drm_dev_alloc(dev, driver, size, offset); if (IS_ERR(container)) return ERR_CAST(container); @@ -109,7 +104,7 @@ __drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, return drm; } -EXPORT_SYMBOL_GPL(__drm_kunit_helper_alloc_drm_device); +EXPORT_SYMBOL_GPL(__drm_kunit_helper_alloc_drm_device_with_driver); MODULE_AUTHOR("Maxime Ripard "); MODULE_LICENSE("GPL"); diff --git a/include/drm/drm_kunit_helpers.h b/include/drm/drm_kunit_helpers.h index df99fda95e89..ed013fdcc1ff 100644 --- a/include/drm/drm_kunit_helpers.h +++ b/include/drm/drm_kunit_helpers.h @@ -3,6 +3,8 @@ #ifndef DRM_KUNIT_HELPERS_H_ #define DRM_KUNIT_HELPERS_H_ +#include + struct drm_device; struct kunit; @@ -10,9 +12,54 @@ struct device *drm_kunit_helper_alloc_device(struct kunit *test); void drm_kunit_helper_free_device(struct kunit *test, struct device *dev); struct drm_device * -__drm_kunit_helper_alloc_drm_device(struct kunit *test, struct device *dev, +__drm_kunit_helper_alloc_drm_device_with_driver(struct kunit *test, + struct device *dev, + size_t size, size_t offset, + const struct drm_driver *driver); + +/** + * drm_kunit_helper_alloc_drm_device_with_driver - Allocates a mock DRM device for KUnit tests + * @_test: The test context object + * @_dev: The parent device object + * @_type: the type of the struct which contains struct &drm_device + * @_member: the name of the &drm_device within @_type. + * @_drv: Mocked DRM device driver features + * + * This function creates a struct &drm_device from @_dev and @_drv. + * + * @_dev should be allocated using drm_kunit_helper_alloc_device(). + * + * The driver is tied to the @_test context and will get cleaned at the + * end of the test. The drm_device is allocated through + * devm_drm_dev_alloc() and will thus be freed through a device-managed + * resource. + * + * Returns: + * A pointer to the new drm_device, or an ERR_PTR() otherwise. + */ +#define drm_kunit_helper_alloc_drm_device_with_driver(_test, _dev, _type, _member, _drv) \ + ((_type *)__drm_kunit_helper_alloc_drm_device_with_driver(_test, _dev, \ + sizeof(_type), \ + offsetof(_type, _member), \ + _drv)) + +static inline struct drm_device * +__drm_kunit_helper_alloc_drm_device(struct kunit *test, + struct device *dev, size_t size, size_t offset, - u32 features); + u32 features) +{ + struct drm_driver *driver; + + driver = kunit_kzalloc(test, sizeof(*driver), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, driver); + + driver->driver_features = features; + + return __drm_kunit_helper_alloc_drm_device_with_driver(test, dev, + size, offset, + driver); +} /** * drm_kunit_helper_alloc_drm_device - Allocates a mock DRM device for KUnit tests -- cgit v1.2.3 From 4e910d9d13e122a7a1263cd820d164c409d6a766 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Mon, 5 Dec 2022 17:33:25 +0000 Subject: drm/bridge: Drop unused drm_bridge_chain functions The drm_bridge_chain_{pre_enable,enable,disable,post_disable} has no users left and we have atomic variants that should be used. Drop them so they do not gain new users. Adjust a few comments to avoid references to the dropped functions. Signed-off-by: Sam Ravnborg Reviewed-by: Maxime Ripard Reviewed-by: Laurent Pinchart Cc: Laurent Pinchart Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Robert Foss Cc: Daniel Vetter Signed-off-by: Dave Stevenson Link: https://lore.kernel.org/r/20221205173328.1395350-4-dave.stevenson@raspberrypi.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_bridge.c | 110 ------------------------------------------- include/drm/drm_bridge.h | 28 ----------- 2 files changed, 138 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 1545c50fd1c8..bb7fc09267af 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -509,61 +509,6 @@ drm_bridge_chain_mode_valid(struct drm_bridge *bridge, } EXPORT_SYMBOL(drm_bridge_chain_mode_valid); -/** - * drm_bridge_chain_disable - disables all bridges in the encoder chain - * @bridge: bridge control structure - * - * Calls &drm_bridge_funcs.disable op for all the bridges in the encoder - * chain, starting from the last bridge to the first. These are called before - * calling the encoder's prepare op. - * - * Note: the bridge passed should be the one closest to the encoder - */ -void drm_bridge_chain_disable(struct drm_bridge *bridge) -{ - struct drm_encoder *encoder; - struct drm_bridge *iter; - - if (!bridge) - return; - - encoder = bridge->encoder; - list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { - if (iter->funcs->disable) - iter->funcs->disable(iter); - - if (iter == bridge) - break; - } -} -EXPORT_SYMBOL(drm_bridge_chain_disable); - -/** - * drm_bridge_chain_post_disable - cleans up after disabling all bridges in the - * encoder chain - * @bridge: bridge control structure - * - * Calls &drm_bridge_funcs.post_disable op for all the bridges in the - * encoder chain, starting from the first bridge to the last. These are called - * after completing the encoder's prepare op. - * - * Note: the bridge passed should be the one closest to the encoder - */ -void drm_bridge_chain_post_disable(struct drm_bridge *bridge) -{ - struct drm_encoder *encoder; - - if (!bridge) - return; - - encoder = bridge->encoder; - list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { - if (bridge->funcs->post_disable) - bridge->funcs->post_disable(bridge); - } -} -EXPORT_SYMBOL(drm_bridge_chain_post_disable); - /** * drm_bridge_chain_mode_set - set proposed mode for all bridges in the * encoder chain @@ -593,61 +538,6 @@ void drm_bridge_chain_mode_set(struct drm_bridge *bridge, } EXPORT_SYMBOL(drm_bridge_chain_mode_set); -/** - * drm_bridge_chain_pre_enable - prepares for enabling all bridges in the - * encoder chain - * @bridge: bridge control structure - * - * Calls &drm_bridge_funcs.pre_enable op for all the bridges in the encoder - * chain, starting from the last bridge to the first. These are called - * before calling the encoder's commit op. - * - * Note: the bridge passed should be the one closest to the encoder - */ -void drm_bridge_chain_pre_enable(struct drm_bridge *bridge) -{ - struct drm_encoder *encoder; - struct drm_bridge *iter; - - if (!bridge) - return; - - encoder = bridge->encoder; - list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { - if (iter->funcs->pre_enable) - iter->funcs->pre_enable(iter); - - if (iter == bridge) - break; - } -} -EXPORT_SYMBOL(drm_bridge_chain_pre_enable); - -/** - * drm_bridge_chain_enable - enables all bridges in the encoder chain - * @bridge: bridge control structure - * - * Calls &drm_bridge_funcs.enable op for all the bridges in the encoder - * chain, starting from the first bridge to the last. These are called - * after completing the encoder's commit op. - * - * Note that the bridge passed should be the one closest to the encoder - */ -void drm_bridge_chain_enable(struct drm_bridge *bridge) -{ - struct drm_encoder *encoder; - - if (!bridge) - return; - - encoder = bridge->encoder; - list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { - if (bridge->funcs->enable) - bridge->funcs->enable(bridge); - } -} -EXPORT_SYMBOL(drm_bridge_chain_enable); - /** * drm_atomic_bridge_chain_disable - disables all bridges in the encoder chain * @bridge: bridge control structure diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 6b65b0dfb4fb..796567a203ac 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -297,12 +297,6 @@ struct drm_bridge_funcs { * not enable the display link feeding the next bridge in the chain (if * there is one) when this callback is called. * - * Note that this function will only be invoked in the context of an - * atomic commit. It will not be invoked from - * &drm_bridge_chain_pre_enable. It would be prudent to also provide an - * implementation of @pre_enable if you are expecting driver calls into - * &drm_bridge_chain_pre_enable. - * * The @atomic_pre_enable callback is optional. */ void (*atomic_pre_enable)(struct drm_bridge *bridge, @@ -323,11 +317,6 @@ struct drm_bridge_funcs { * callback must enable the display link feeding the next bridge in the * chain if there is one. * - * Note that this function will only be invoked in the context of an - * atomic commit. It will not be invoked from &drm_bridge_chain_enable. - * It would be prudent to also provide an implementation of @enable if - * you are expecting driver calls into &drm_bridge_chain_enable. - * * The @atomic_enable callback is optional. */ void (*atomic_enable)(struct drm_bridge *bridge, @@ -345,12 +334,6 @@ struct drm_bridge_funcs { * The bridge can assume that the display pipe (i.e. clocks and timing * signals) feeding it is still running when this callback is called. * - * Note that this function will only be invoked in the context of an - * atomic commit. It will not be invoked from - * &drm_bridge_chain_disable. It would be prudent to also provide an - * implementation of @disable if you are expecting driver calls into - * &drm_bridge_chain_disable. - * * The @atomic_disable callback is optional. */ void (*atomic_disable)(struct drm_bridge *bridge, @@ -370,13 +353,6 @@ struct drm_bridge_funcs { * signals) feeding it is no longer running when this callback is * called. * - * Note that this function will only be invoked in the context of an - * atomic commit. It will not be invoked from - * &drm_bridge_chain_post_disable. - * It would be prudent to also provide an implementation of - * @post_disable if you are expecting driver calls into - * &drm_bridge_chain_post_disable. - * * The @atomic_post_disable callback is optional. */ void (*atomic_post_disable)(struct drm_bridge *bridge, @@ -876,13 +852,9 @@ enum drm_mode_status drm_bridge_chain_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode); -void drm_bridge_chain_disable(struct drm_bridge *bridge); -void drm_bridge_chain_post_disable(struct drm_bridge *bridge); void drm_bridge_chain_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode); -void drm_bridge_chain_pre_enable(struct drm_bridge *bridge); -void drm_bridge_chain_enable(struct drm_bridge *bridge); int drm_atomic_bridge_chain_check(struct drm_bridge *bridge, struct drm_crtc_state *crtc_state, -- cgit v1.2.3 From 4fb912e5e19075874379cfcf074d90bd51ebf8ea Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 5 Dec 2022 17:33:26 +0000 Subject: drm/bridge: Introduce pre_enable_prev_first to alter bridge init order DSI sink devices typically want the DSI host powered up and configured before they are powered up. pre_enable is the place this would normally happen, but they are called in reverse order from panel/connector towards the encoder, which is the "wrong" order. Add a new flag pre_enable_prev_first that any bridge can set to swap the order of pre_enable (and post_disable) for that and the immediately previous bridge. Should the immediately previous bridge also set the pre_enable_prev_first flag, the previous bridge to that will be called before either of those which requested pre_enable_prev_first. eg: - Panel - Bridge 1 - Bridge 2 pre_enable_prev_first - Bridge 3 - Bridge 4 pre_enable_prev_first - Bridge 5 pre_enable_prev_first - Bridge 6 - Encoder Would result in pre_enable's being called as Panel, Bridge 1, Bridge 3, Bridge 2, Bridge 6, Bridge 5, Bridge 4, Encoder. Signed-off-by: Dave Stevenson Tested-by: Frieder Schrempf Reviewed-by: Frieder Schrempf Link: https://lore.kernel.org/r/20221205173328.1395350-5-dave.stevenson@raspberrypi.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/drm_bridge.c | 145 ++++++++++++++++++++++++++++++++++++------- include/drm/drm_bridge.h | 8 +++ 2 files changed, 129 insertions(+), 24 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index bb7fc09267af..5f40c83b1b42 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -581,6 +581,25 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge, } EXPORT_SYMBOL(drm_atomic_bridge_chain_disable); +static void drm_atomic_bridge_call_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *old_state) +{ + if (old_state && bridge->funcs->atomic_post_disable) { + struct drm_bridge_state *old_bridge_state; + + old_bridge_state = + drm_atomic_get_old_bridge_state(old_state, + bridge); + if (WARN_ON(!old_bridge_state)) + return; + + bridge->funcs->atomic_post_disable(bridge, + old_bridge_state); + } else if (bridge->funcs->post_disable) { + bridge->funcs->post_disable(bridge); + } +} + /** * drm_atomic_bridge_chain_post_disable - cleans up after disabling all bridges * in the encoder chain @@ -592,36 +611,86 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_disable); * starting from the first bridge to the last. These are called after completing * &drm_encoder_helper_funcs.atomic_disable * + * If a bridge sets @pre_enable_prev_first, then the @post_disable for that + * bridge will be called before the previous one to reverse the @pre_enable + * calling direction. + * * Note: the bridge passed should be the one closest to the encoder */ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge, struct drm_atomic_state *old_state) { struct drm_encoder *encoder; + struct drm_bridge *next, *limit; if (!bridge) return; encoder = bridge->encoder; + list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) { - if (bridge->funcs->atomic_post_disable) { - struct drm_bridge_state *old_bridge_state; + limit = NULL; + + if (!list_is_last(&bridge->chain_node, &encoder->bridge_chain)) { + next = list_next_entry(bridge, chain_node); + + if (next->pre_enable_prev_first) { + /* next bridge had requested that prev + * was enabled first, so disabled last + */ + limit = next; + + /* Find the next bridge that has NOT requested + * prev to be enabled first / disabled last + */ + list_for_each_entry_from(next, &encoder->bridge_chain, + chain_node) { + if (next->pre_enable_prev_first) { + next = list_prev_entry(next, chain_node); + limit = next; + break; + } + } + + /* Call these bridges in reverse order */ + list_for_each_entry_from_reverse(next, &encoder->bridge_chain, + chain_node) { + if (next == bridge) + break; + + drm_atomic_bridge_call_post_disable(next, + old_state); + } + } + } - old_bridge_state = - drm_atomic_get_old_bridge_state(old_state, - bridge); - if (WARN_ON(!old_bridge_state)) - return; + drm_atomic_bridge_call_post_disable(bridge, old_state); - bridge->funcs->atomic_post_disable(bridge, - old_bridge_state); - } else if (bridge->funcs->post_disable) { - bridge->funcs->post_disable(bridge); - } + if (limit) + /* Jump all bridges that we have already post_disabled */ + bridge = limit; } } EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable); +static void drm_atomic_bridge_call_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *old_state) +{ + if (old_state && bridge->funcs->atomic_pre_enable) { + struct drm_bridge_state *old_bridge_state; + + old_bridge_state = + drm_atomic_get_old_bridge_state(old_state, + bridge); + if (WARN_ON(!old_bridge_state)) + return; + + bridge->funcs->atomic_pre_enable(bridge, old_bridge_state); + } else if (bridge->funcs->pre_enable) { + bridge->funcs->pre_enable(bridge); + } +} + /** * drm_atomic_bridge_chain_pre_enable - prepares for enabling all bridges in * the encoder chain @@ -633,32 +702,60 @@ EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable); * starting from the last bridge to the first. These are called before calling * &drm_encoder_helper_funcs.atomic_enable * + * If a bridge sets @pre_enable_prev_first, then the pre_enable for the + * prev bridge will be called before pre_enable of this bridge. + * * Note: the bridge passed should be the one closest to the encoder */ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge, struct drm_atomic_state *old_state) { struct drm_encoder *encoder; - struct drm_bridge *iter; + struct drm_bridge *iter, *next, *limit; if (!bridge) return; encoder = bridge->encoder; + list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { - if (iter->funcs->atomic_pre_enable) { - struct drm_bridge_state *old_bridge_state; + if (iter->pre_enable_prev_first) { + next = iter; + limit = bridge; + list_for_each_entry_from_reverse(next, + &encoder->bridge_chain, + chain_node) { + if (next == bridge) + break; + + if (!next->pre_enable_prev_first) { + /* Found first bridge that does NOT + * request prev to be enabled first + */ + limit = list_prev_entry(next, chain_node); + break; + } + } + + list_for_each_entry_from(next, &encoder->bridge_chain, chain_node) { + /* Call requested prev bridge pre_enable + * in order. + */ + if (next == iter) + /* At the first bridge to request prev + * bridges called first. + */ + break; + + drm_atomic_bridge_call_pre_enable(next, old_state); + } + } - old_bridge_state = - drm_atomic_get_old_bridge_state(old_state, - iter); - if (WARN_ON(!old_bridge_state)) - return; + drm_atomic_bridge_call_pre_enable(iter, old_state); - iter->funcs->atomic_pre_enable(iter, old_bridge_state); - } else if (iter->funcs->pre_enable) { - iter->funcs->pre_enable(iter); - } + if (iter->pre_enable_prev_first) + /* Jump all bridges that we have already pre_enabled */ + iter = limit; if (iter == bridge) break; diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h index 796567a203ac..42f86327b40a 100644 --- a/include/drm/drm_bridge.h +++ b/include/drm/drm_bridge.h @@ -744,6 +744,14 @@ struct drm_bridge { * modes. */ bool interlace_allowed; + /** + * @pre_enable_prev_first: The bridge requires that the prev + * bridge @pre_enable function is called before its @pre_enable, + * and conversely for post_disable. This is most frequently a + * requirement for DSI devices which need the host to be initialised + * before the peripheral. + */ + bool pre_enable_prev_first; /** * @ddc: Associated I2C adapter for DDC access, if any. */ -- cgit v1.2.3 From 5ea6b17027810ffbdb5bea7d0a2b1d312dd1021c Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Mon, 5 Dec 2022 17:33:27 +0000 Subject: drm/panel: Add prepare_prev_first flag to drm_panel Mapping to the drm_bridge flag pre_enable_prev_first, add a new flag prepare_prev_first to drm_panel to allow the panel driver to request that the upstream bridge should be pre_enabled before the panel prepare. Signed-off-by: Dave Stevenson Reviewed-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20221205173328.1395350-6-dave.stevenson@raspberrypi.com Signed-off-by: Maxime Ripard --- drivers/gpu/drm/bridge/panel.c | 2 ++ include/drm/drm_panel.h | 10 ++++++++++ 2 files changed, 12 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 216af76d0042..03c3274dc3d9 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -364,6 +364,8 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev, devres_free(ptr); } + bridge->pre_enable_prev_first = panel->prepare_prev_first; + return bridge; } EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 994bfcdd84c5..432fab2347eb 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -188,6 +188,16 @@ struct drm_panel { * Panel entry in registry. */ struct list_head list; + + /** + * @prepare_prev_first: + * + * The previous controller should be prepared first, before the prepare + * for the panel is called. This is largely required for DSI panels + * where the DSI host controller should be initialised to LP-11 before + * the panel is powered up. + */ + bool prepare_prev_first; }; void drm_panel_init(struct drm_panel *panel, struct device *dev, -- cgit v1.2.3 From 1482ec00be4a3634aeffbcc799791a723df69339 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 1 Nov 2022 11:42:17 +0200 Subject: drm: Add missing DP DSC extended capability definitions. Adding DP DSC register definitions, we might need for further DSC implementation, supporting MST and DP branch pass-through mode. v2: - Fixed checkpatch comment warning v3: - Removed function which is not yet used(Jani Nikula) Reviewed-by: Vinod Govindapillai Acked-by: Maarten Lankhorst Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20221101094222.22091-2-stanislav.lisovskiy@intel.com --- include/drm/display/drm_dp.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index e934aab357be..9bc22a02874d 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -240,6 +240,8 @@ #define DP_DSC_SUPPORT 0x060 /* DP 1.4 */ # define DP_DSC_DECOMPRESSION_IS_SUPPORTED (1 << 0) # define DP_DSC_PASSTHROUGH_IS_SUPPORTED (1 << 1) +# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_COMP_TO_COMP (1 << 2) +# define DP_DSC_DYNAMIC_PPS_UPDATE_SUPPORT_UNCOMP_TO_COMP (1 << 3) #define DP_DSC_REV 0x061 # define DP_DSC_MAJOR_MASK (0xf << 0) @@ -278,12 +280,15 @@ #define DP_DSC_BLK_PREDICTION_SUPPORT 0x066 # define DP_DSC_BLK_PREDICTION_IS_SUPPORTED (1 << 0) +# define DP_DSC_RGB_COLOR_CONV_BYPASS_SUPPORT (1 << 1) #define DP_DSC_MAX_BITS_PER_PIXEL_LOW 0x067 /* eDP 1.4 */ #define DP_DSC_MAX_BITS_PER_PIXEL_HI 0x068 /* eDP 1.4 */ # define DP_DSC_MAX_BITS_PER_PIXEL_HI_MASK (0x3 << 0) # define DP_DSC_MAX_BITS_PER_PIXEL_HI_SHIFT 8 +# define DP_DSC_MAX_BPP_DELTA_VERSION_MASK 0x06 +# define DP_DSC_MAX_BPP_DELTA_AVAILABILITY 0x08 #define DP_DSC_DEC_COLOR_FORMAT_CAP 0x069 # define DP_DSC_RGB (1 << 0) @@ -345,11 +350,13 @@ # define DP_DSC_24_PER_DP_DSC_SINK (1 << 2) #define DP_DSC_BITS_PER_PIXEL_INC 0x06F +# define DP_DSC_RGB_YCbCr444_MAX_BPP_DELTA_MASK 0x1f +# define DP_DSC_RGB_YCbCr420_MAX_BPP_DELTA_MASK 0xe0 # define DP_DSC_BITS_PER_PIXEL_1_16 0x0 # define DP_DSC_BITS_PER_PIXEL_1_8 0x1 # define DP_DSC_BITS_PER_PIXEL_1_4 0x2 # define DP_DSC_BITS_PER_PIXEL_1_2 0x3 -# define DP_DSC_BITS_PER_PIXEL_1 0x4 +# define DP_DSC_BITS_PER_PIXEL_1_1 0x4 #define DP_PSR_SUPPORT 0x070 /* XXX 1.2? */ # define DP_PSR_IS_SUPPORTED 1 -- cgit v1.2.3 From 3b1fb8b3a3f8a4e645ef580edaeed35ec3f73c38 Mon Sep 17 00:00:00 2001 From: Otto Pflüger Date: Thu, 1 Dec 2022 17:02:43 +0100 Subject: drm/mipi-dbi: Support separate I/O regulator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The MIPI DBI specification defines separate vdd (panel power) and vddi (I/O voltage) supplies. Displays that require different voltages for the different supplies do exist, so the supplies cannot be combined into one as they are now. Add a new io_regulator property to the mipi_dbi_dev struct which can be set by the panel driver along with the regulator property. Signed-off-by: Otto Pflüger Reviewed-by: Noralf Trønnes Signed-off-by: Noralf Trønnes Link: https://patchwork.freedesktop.org/patch/msgid/20221201160245.2093816-2-otto.pflueger@abscue.de --- drivers/gpu/drm/drm_mipi_dbi.c | 14 ++++++++++++++ include/drm/drm_mipi_dbi.h | 7 ++++++- 2 files changed, 20 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index eb27d000bcfb..c871d9f096b8 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -417,6 +417,8 @@ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) if (dbidev->regulator) regulator_disable(dbidev->regulator); + if (dbidev->io_regulator) + regulator_disable(dbidev->io_regulator); } EXPORT_SYMBOL(mipi_dbi_pipe_disable); @@ -726,6 +728,16 @@ static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi_dev *dbidev, bool } } + if (dbidev->io_regulator) { + ret = regulator_enable(dbidev->io_regulator); + if (ret) { + DRM_DEV_ERROR(dev, "Failed to enable I/O regulator (%d)\n", ret); + if (dbidev->regulator) + regulator_disable(dbidev->regulator); + return ret; + } + } + if (cond && mipi_dbi_display_is_on(dbi)) return 1; @@ -735,6 +747,8 @@ static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi_dev *dbidev, bool DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret); if (dbidev->regulator) regulator_disable(dbidev->regulator); + if (dbidev->io_regulator) + regulator_disable(dbidev->io_regulator); return ret; } diff --git a/include/drm/drm_mipi_dbi.h b/include/drm/drm_mipi_dbi.h index 304fbecdc66a..816f196b3d4c 100644 --- a/include/drm/drm_mipi_dbi.h +++ b/include/drm/drm_mipi_dbi.h @@ -123,10 +123,15 @@ struct mipi_dbi_dev { struct backlight_device *backlight; /** - * @regulator: power regulator (optional) + * @regulator: power regulator (Vdd) (optional) */ struct regulator *regulator; + /** + * @io_regulator: I/O power regulator (Vddi) (optional) + */ + struct regulator *io_regulator; + /** * @dbi: MIPI DBI interface */ -- cgit v1.2.3 From 50371be6c7b7c1b40afc1e7f215d60f7f41913c4 Mon Sep 17 00:00:00 2001 From: Sung Joon Kim Date: Thu, 8 Dec 2022 13:55:45 -0500 Subject: drm/display: Add missing Adaptive Sync DPCD definitions The missing DPCD definitions from DP2.0 spec is as follows: DOWNSPREAD_CTRL (107h): FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE (bit 6) For sink devices that support Adaptive-Sync operation and Panel Replay DPRX_FEATURE_ENUMERATION_LIST_CONT_1 (2214h): ADAPTIVE_SYNC_SDP_SUPPORTED (bit 0) Bit to check sink device has Adaptive-Sync capability AS_SDP_FIRST_HALF_LINE_OR_3840_PIXEL_CYCLE_WINDOW_NOT_SUPPORTED (bit 1) A sink device that clears this bit will generate VSync pulse leading edge of the HDMI output on the line count at which Adaptive-Sync SDP is received as long as source device transmits Adaptive-Sync SDP either in first line or first 3840 pixel cycles of the line whichever occurs first. VSC_EXT_SDP_FRAMEWORK_VERSION_1_SUPPORTED (bit 4) Bit to check sink device has SDP framework version 1 capability Signed-off-by: Sung Joon Kim Reviewed-by: Harry Wentland Signed-off-by: Alex Deucher --- include/drm/display/drm_dp.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include') diff --git a/include/drm/display/drm_dp.h b/include/drm/display/drm_dp.h index e934aab357be..ed10e6b6f99d 100644 --- a/include/drm/display/drm_dp.h +++ b/include/drm/display/drm_dp.h @@ -603,6 +603,7 @@ #define DP_DOWNSPREAD_CTRL 0x107 # define DP_SPREAD_AMP_0_5 (1 << 4) +# define DP_FIXED_VTOTAL_AS_SDP_EN_IN_PR_ACTIVE (1 << 6) # define DP_MSA_TIMING_PAR_IGNORE_EN (1 << 7) /* eDP */ #define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 @@ -1105,6 +1106,11 @@ # define DP_VSC_EXT_CEA_SDP_SUPPORTED (1 << 6) /* DP 1.4 */ # define DP_VSC_EXT_CEA_SDP_CHAINING_SUPPORTED (1 << 7) /* DP 1.4 */ +#define DP_DPRX_FEATURE_ENUMERATION_LIST_CONT_1 0x2214 /* 2.0 E11 */ +# define DP_ADAPTIVE_SYNC_SDP_SUPPORTED (1 << 0) +# define DP_AS_SDP_FIRST_HALF_LINE_OR_3840_PIXEL_CYCLE_WINDOW_NOT_SUPPORTED (1 << 1) +# define DP_VSC_EXT_SDP_FRAMEWORK_VERSION_1_SUPPORTED (1 << 4) + #define DP_128B132B_SUPPORTED_LINK_RATES 0x2215 /* 2.0 */ # define DP_UHBR10 (1 << 0) # define DP_UHBR20 (1 << 1) -- cgit v1.2.3 From 5cfd978490d82486fc3286a72009fb3229760555 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 5 Dec 2022 14:43:00 +0800 Subject: drm/amdgpu: expose peak profiling mode shader/memory clocks Expose those informations to UMD who need them as for standard profiling mode. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 18 ++++++++++++++++++ include/uapi/drm/amdgpu_drm.h | 4 ++++ 2 files changed, 22 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 7aa7e52ca784..095995a1f084 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1014,6 +1014,24 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) } ui32 /= 100; break; + case AMDGPU_INFO_SENSOR_PEAK_PSTATE_GFX_SCLK: + /* get peak pstate sclk in Mhz */ + if (amdgpu_dpm_read_sensor(adev, + AMDGPU_PP_SENSOR_PEAK_PSTATE_SCLK, + (void *)&ui32, &ui32_size)) { + return -EINVAL; + } + ui32 /= 100; + break; + case AMDGPU_INFO_SENSOR_PEAK_PSTATE_GFX_MCLK: + /* get peak pstate mclk in Mhz */ + if (amdgpu_dpm_read_sensor(adev, + AMDGPU_PP_SENSOR_PEAK_PSTATE_MCLK, + (void *)&ui32, &ui32_size)) { + return -EINVAL; + } + ui32 /= 100; + break; default: DRM_DEBUG_KMS("Invalid request %d\n", info->sensor_info.type); diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 4038abe8505a..8c5d05384767 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -832,6 +832,10 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_SCLK 0x8 /* Subquery id: Query GPU stable pstate memory clock */ #define AMDGPU_INFO_SENSOR_STABLE_PSTATE_GFX_MCLK 0x9 + /* Subquery id: Query GPU peak pstate shader clock */ + #define AMDGPU_INFO_SENSOR_PEAK_PSTATE_GFX_SCLK 0xa + /* Subquery id: Query GPU peak pstate memory clock */ + #define AMDGPU_INFO_SENSOR_PEAK_PSTATE_GFX_MCLK 0xb /* Number of VRAM page faults on CPU access. */ #define AMDGPU_INFO_NUM_VRAM_CPU_PAGE_FAULTS 0x1E #define AMDGPU_INFO_VRAM_LOST_COUNTER 0x1F -- cgit v1.2.3 From 88347fa18bead86949c45229faaa2c66177c62fb Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Mon, 5 Dec 2022 10:09:38 +0800 Subject: drm/amdgpu: expose the minimum shader/memory clock frequency Otherwise, some UMD tools will treate them as 0 at default while actually they are not. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 10 ++++++++-- include/uapi/drm/amdgpu_drm.h | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 095995a1f084..2947159d7d78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -785,9 +785,15 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (adev->pm.dpm_enabled) { dev_info->max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10; dev_info->max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10; + dev_info->min_engine_clock = amdgpu_dpm_get_sclk(adev, true) * 10; + dev_info->min_memory_clock = amdgpu_dpm_get_mclk(adev, true) * 10; } else { - dev_info->max_engine_clock = adev->clock.default_sclk * 10; - dev_info->max_memory_clock = adev->clock.default_mclk * 10; + dev_info->max_engine_clock = + dev_info->min_engine_clock = + adev->clock.default_sclk * 10; + dev_info->max_memory_clock = + dev_info->min_memory_clock = + adev->clock.default_mclk * 10; } dev_info->enabled_rb_pipes_mask = adev->gfx.config.backend_enable_mask; dev_info->num_rb_pipes = adev->gfx.config.max_backends_per_se * diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index 8c5d05384767..fe7f871e3080 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -1111,6 +1111,8 @@ struct drm_amdgpu_info_device { __u32 pa_sc_tile_steering_override; /* disabled TCCs */ __u64 tcc_disabled_mask; + __u64 min_engine_clock; + __u64 min_memory_clock; }; struct drm_amdgpu_info_hw_ip { -- cgit v1.2.3 From 1c9cacbea880513a896aee65a5c58007bcb55653 Mon Sep 17 00:00:00 2001 From: Maíra Canal Date: Mon, 19 Dec 2022 09:06:15 -0300 Subject: drm/debugfs: create device-centered debugfs functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce the ability to track requests for the addition of DRM debugfs files at any time and have them added all at once during drm_dev_register(). Drivers can add DRM debugfs files to a device-managed list and, during drm_dev_register(), all added files will be created at once. Now, the drivers can use the functions drm_debugfs_add_file() and drm_debugfs_add_files() to create DRM debugfs files instead of using the drm_debugfs_create_files() function. Co-developed-by: Wambui Karuga Signed-off-by: Wambui Karuga Signed-off-by: Maíra Canal Reviewed-by: Maxime Ripard Reviewed-by: Melissa Wen Acked-by: Daniel Vetter Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20221219120621.15086-2-mcanal@igalia.com --- drivers/gpu/drm/drm_debugfs.c | 70 +++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_drv.c | 3 ++ include/drm/drm_debugfs.h | 41 +++++++++++++++++++++++++ include/drm/drm_device.h | 15 ++++++++++ 4 files changed, 129 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index ee445f4605ba..988fc07b94b4 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -38,6 +38,7 @@ #include #include #include +#include #include "drm_crtc_internal.h" #include "drm_internal.h" @@ -151,6 +152,21 @@ static int drm_debugfs_open(struct inode *inode, struct file *file) return single_open(file, node->info_ent->show, node); } +static int drm_debugfs_entry_open(struct inode *inode, struct file *file) +{ + struct drm_debugfs_entry *entry = inode->i_private; + struct drm_debugfs_info *node = &entry->file; + + return single_open(file, node->show, entry); +} + +static const struct file_operations drm_debugfs_entry_fops = { + .owner = THIS_MODULE, + .open = drm_debugfs_entry_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; static const struct file_operations drm_debugfs_fops = { .owner = THIS_MODULE, @@ -207,6 +223,7 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, struct dentry *root) { struct drm_device *dev = minor->dev; + struct drm_debugfs_entry *entry, *tmp; char name[64]; INIT_LIST_HEAD(&minor->debugfs_list); @@ -230,6 +247,12 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id, if (dev->driver->debugfs_init) dev->driver->debugfs_init(minor); + list_for_each_entry_safe(entry, tmp, &dev->debugfs_list, list) { + debugfs_create_file(entry->file.name, S_IFREG | S_IRUGO, + minor->debugfs_root, entry, &drm_debugfs_entry_fops); + list_del(&entry->list); + } + return 0; } @@ -281,6 +304,53 @@ void drm_debugfs_cleanup(struct drm_minor *minor) minor->debugfs_root = NULL; } +/** + * drm_debugfs_add_file - Add a given file to the DRM device debugfs file list + * @dev: drm device for the ioctl + * @name: debugfs file name + * @show: show callback + * @data: driver-private data, should not be device-specific + * + * Add a given file entry to the DRM device debugfs file list to be created on + * drm_debugfs_init. + */ +void drm_debugfs_add_file(struct drm_device *dev, const char *name, + int (*show)(struct seq_file*, void*), void *data) +{ + struct drm_debugfs_entry *entry = drmm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); + + if (!entry) + return; + + entry->file.name = name; + entry->file.show = show; + entry->file.data = data; + entry->dev = dev; + + mutex_lock(&dev->debugfs_mutex); + list_add(&entry->list, &dev->debugfs_list); + mutex_unlock(&dev->debugfs_mutex); +} +EXPORT_SYMBOL(drm_debugfs_add_file); + +/** + * drm_debugfs_add_files - Add an array of files to the DRM device debugfs file list + * @dev: drm device for the ioctl + * @files: The array of files to create + * @count: The number of files given + * + * Add a given set of debugfs files represented by an array of + * &struct drm_debugfs_info in the DRM device debugfs file list. + */ +void drm_debugfs_add_files(struct drm_device *dev, const struct drm_debugfs_info *files, int count) +{ + int i; + + for (i = 0; i < count; i++) + drm_debugfs_add_file(dev, files[i].name, files[i].show, files[i].data); +} +EXPORT_SYMBOL(drm_debugfs_add_files); + static int connector_show(struct seq_file *m, void *data) { struct drm_connector *connector = m->private; diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 3cc8e8111d16..11748dd513c3 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -575,6 +575,7 @@ static void drm_dev_init_release(struct drm_device *dev, void *res) mutex_destroy(&dev->clientlist_mutex); mutex_destroy(&dev->filelist_mutex); mutex_destroy(&dev->struct_mutex); + mutex_destroy(&dev->debugfs_mutex); drm_legacy_destroy_members(dev); } @@ -608,12 +609,14 @@ static int drm_dev_init(struct drm_device *dev, INIT_LIST_HEAD(&dev->filelist_internal); INIT_LIST_HEAD(&dev->clientlist); INIT_LIST_HEAD(&dev->vblank_event_list); + INIT_LIST_HEAD(&dev->debugfs_list); spin_lock_init(&dev->event_lock); mutex_init(&dev->struct_mutex); mutex_init(&dev->filelist_mutex); mutex_init(&dev->clientlist_mutex); mutex_init(&dev->master_mutex); + mutex_init(&dev->debugfs_mutex); ret = drmm_add_action_or_reset(dev, drm_dev_init_release, NULL); if (ret) diff --git a/include/drm/drm_debugfs.h b/include/drm/drm_debugfs.h index 2188dc83957f..53b7297260a5 100644 --- a/include/drm/drm_debugfs.h +++ b/include/drm/drm_debugfs.h @@ -79,12 +79,43 @@ struct drm_info_node { struct dentry *dent; }; +/** + * struct drm_debugfs_info - debugfs info list entry + * + * This structure represents a debugfs file to be created by the drm + * core. + */ +struct drm_debugfs_info { + const char *name; + int (*show)(struct seq_file*, void*); + u32 driver_features; + void *data; +}; + +/** + * struct drm_debugfs_entry - Per-device debugfs node structure + * + * This structure represents a debugfs file, as an instantiation of a &struct + * drm_debugfs_info on a &struct drm_device. + */ +struct drm_debugfs_entry { + struct drm_device *dev; + struct drm_debugfs_info file; + struct list_head list; +}; + #if defined(CONFIG_DEBUG_FS) void drm_debugfs_create_files(const struct drm_info_list *files, int count, struct dentry *root, struct drm_minor *minor); int drm_debugfs_remove_files(const struct drm_info_list *files, int count, struct drm_minor *minor); + +void drm_debugfs_add_file(struct drm_device *dev, const char *name, + int (*show)(struct seq_file*, void*), void *data); + +void drm_debugfs_add_files(struct drm_device *dev, + const struct drm_debugfs_info *files, int count); #else static inline void drm_debugfs_create_files(const struct drm_info_list *files, int count, struct dentry *root, @@ -96,6 +127,16 @@ static inline int drm_debugfs_remove_files(const struct drm_info_list *files, { return 0; } + +static inline void drm_debugfs_add_file(struct drm_device *dev, const char *name, + int (*show)(struct seq_file*, void*), + void *data) +{} + +static inline void drm_debugfs_add_files(struct drm_device *dev, + const struct drm_debugfs_info *files, + int count) +{} #endif #endif /* _DRM_DEBUGFS_H_ */ diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index 9923c7a6885e..fa6af1d57929 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -295,6 +295,21 @@ struct drm_device { */ struct drm_fb_helper *fb_helper; + /** + * @debugfs_mutex: + * + * Protects &debugfs_list access. + */ + struct mutex debugfs_mutex; + + /** + * @debugfs_list: + * + * List of debugfs files to be created by the DRM device. The files + * must be added during drm_dev_register(). + */ + struct list_head debugfs_list; + /* Everything below here is for legacy driver, never use! */ /* private: */ #if IS_ENABLED(CONFIG_DRM_LEGACY) -- cgit v1.2.3 From 175073d694cd9db4c4ca97c978a447acc6b5cb33 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Jan 2023 12:29:21 +0100 Subject: drm/format-helper: Add conversion from XRGB8888 to ARGB8888 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add dedicated helper to convert from XRGB8888 to ARGB8888. Sets all alpha bits to make pixels fully opaque. v3: * use __le32 for destination buffer (Jose, kernel test robot) v2: * use cpubuf_to_le32() * type fixes Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20230102112927.26565-8-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 53 +++++++++++++++++++++- drivers/gpu/drm/tests/drm_format_helper_test.c | 63 ++++++++++++++++++++++++++ include/drm/drm_format_helper.h | 3 ++ 3 files changed, 117 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 36d2ca9d0f01..718e29341773 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -446,6 +446,54 @@ void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pi } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888); +static void drm_fb_xrgb8888_to_argb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + __le32 *dbuf32 = dbuf; + const __le32 *sbuf32 = sbuf; + unsigned int x; + u32 pix; + + for (x = 0; x < pixels; x++) { + pix = le32_to_cpu(sbuf32[x]); + pix |= GENMASK(31, 24); /* fill alpha bits */ + dbuf32[x] = cpu_to_le32(pix); + } +} + +/** + * drm_fb_xrgb8888_to_argb8888 - Convert XRGB8888 to ARGB8888 clip buffer + * @dst: Array of ARGB8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for ARGB8888 devices that don't support XRGB8888 + * natively. It sets an opaque alpha channel as part of the conversion. + */ +void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 4, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, + drm_fb_xrgb8888_to_argb8888_line); +} +EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb8888); + static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels) { __le32 *dbuf32 = dbuf; @@ -646,8 +694,6 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d /* treat alpha channel like filler bits */ if (fb_format == DRM_FORMAT_ARGB8888) fb_format = DRM_FORMAT_XRGB8888; - if (dst_format == DRM_FORMAT_ARGB8888) - dst_format = DRM_FORMAT_XRGB8888; if (fb_format == DRM_FORMAT_ARGB2101010) fb_format = DRM_FORMAT_XRGB2101010; if (dst_format == DRM_FORMAT_ARGB2101010) @@ -669,6 +715,9 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } else if (dst_format == DRM_FORMAT_RGB888) { drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip); return 0; + } else if (dst_format == DRM_FORMAT_ARGB8888) { + drm_fb_xrgb8888_to_argb8888(dst, dst_pitch, src, fb, clip); + return 0; } else if (dst_format == DRM_FORMAT_XRGB2101010) { drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip); return 0; diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index c2411ec808a1..bc969413a412 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -37,6 +37,11 @@ struct convert_to_rgb888_result { const u8 expected[TEST_BUF_SIZE]; }; +struct convert_to_argb8888_result { + unsigned int dst_pitch; + const u32 expected[TEST_BUF_SIZE]; +}; + struct convert_to_xrgb2101010_result { unsigned int dst_pitch; const u32 expected[TEST_BUF_SIZE]; @@ -51,6 +56,7 @@ struct convert_xrgb8888_case { struct convert_to_rgb332_result rgb332_result; struct convert_to_rgb565_result rgb565_result; struct convert_to_rgb888_result rgb888_result; + struct convert_to_argb8888_result argb8888_result; struct convert_to_xrgb2101010_result xrgb2101010_result; }; @@ -77,6 +83,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .dst_pitch = 0, .expected = { 0x00, 0x00, 0xFF }, }, + .argb8888_result = { + .dst_pitch = 0, + .expected = { 0xFFFF0000 }, + }, .xrgb2101010_result = { .dst_pitch = 0, .expected = { 0x3FF00000 }, @@ -107,6 +117,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .dst_pitch = 0, .expected = { 0x00, 0x00, 0xFF }, }, + .argb8888_result = { + .dst_pitch = 0, + .expected = { 0xFFFF0000 }, + }, .xrgb2101010_result = { .dst_pitch = 0, .expected = { 0x3FF00000 }, @@ -169,6 +183,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, }, }, + .argb8888_result = { + .dst_pitch = 0, + .expected = { + 0xFFFFFFFF, 0xFF000000, + 0xFFFF0000, 0xFF00FF00, + 0xFF0000FF, 0xFFFF00FF, + 0xFFFFFF00, 0xFF00FFFF, + }, + }, .xrgb2101010_result = { .dst_pitch = 0, .expected = { @@ -229,6 +252,14 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, }, + .argb8888_result = { + .dst_pitch = 20, + .expected = { + 0xFF0E449C, 0xFF114D05, 0xFFA80303, 0x00000000, 0x00000000, + 0xFF6C7073, 0xFF0E449C, 0xFF114D05, 0x00000000, 0x00000000, + 0xFFA80303, 0xFF6C7073, 0xFF0E449C, 0x00000000, 0x00000000, + }, + }, .xrgb2101010_result = { .dst_pitch = 20, .expected = { @@ -448,6 +479,37 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test) KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); } +static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test) +{ + const struct convert_xrgb8888_case *params = test->param_value; + const struct convert_to_argb8888_result *result = ¶ms->argb8888_result; + size_t dst_size; + u32 *buf = NULL; + __le32 *xrgb8888 = NULL; + struct iosys_map dst, src; + + struct drm_framebuffer fb = { + .format = drm_format_info(DRM_FORMAT_XRGB8888), + .pitches = { params->pitch, 0, 0 }, + }; + + dst_size = conversion_buf_size(DRM_FORMAT_ARGB8888, + result->dst_pitch, ¶ms->clip); + KUNIT_ASSERT_GT(test, dst_size, 0); + + buf = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + iosys_map_set_vaddr(&dst, buf); + + xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888); + iosys_map_set_vaddr(&src, xrgb8888); + + drm_fb_xrgb8888_to_argb8888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); + buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); + KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); +} + static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) { const struct convert_xrgb8888_case *params = test->param_value; @@ -484,6 +546,7 @@ static struct kunit_case drm_format_helper_test_cases[] = { KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb565, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params), + KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params), {} }; diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index eb5c98cf82b8..3ce8129dfe43 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -33,6 +33,9 @@ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); +void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip); void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); -- cgit v1.2.3 From 56119bfb39142090fb84ac08a3f14dd48410e961 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Jan 2023 12:29:22 +0100 Subject: drm/format-helper: Add conversion from XRGB8888 to ARGB2101010 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add dedicated helper to convert from XRGB8888 to ARGB2101010. Sets all alpha bits to make pixels fully opaque. v2: * set correct format in struct drm_framebuffer (Javier) * use cpubuf_to_le32() * type fixes Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20230102112927.26565-9-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 58 +++++++++++++++++++++++- drivers/gpu/drm/tests/drm_format_helper_test.c | 63 ++++++++++++++++++++++++++ include/drm/drm_format_helper.h | 3 ++ 3 files changed, 122 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 718e29341773..33780c9183bb 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -605,6 +605,59 @@ void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *d } EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010); +static void drm_fb_xrgb8888_to_argb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + __le32 *dbuf32 = dbuf; + const __le32 *sbuf32 = sbuf; + unsigned int x; + u32 val32; + u32 pix; + + for (x = 0; x < pixels; x++) { + pix = le32_to_cpu(sbuf32[x]); + val32 = ((pix & 0x000000ff) << 2) | + ((pix & 0x0000ff00) << 4) | + ((pix & 0x00ff0000) << 6); + pix = GENMASK(31, 30) | /* set alpha bits */ + val32 | ((val32 >> 8) & 0x00300c03); + *dbuf32++ = cpu_to_le32(pix); + } +} + +/** + * drm_fb_xrgb8888_to_argb2101010 - Convert XRGB8888 to ARGB2101010 clip buffer + * @dst: Array of ARGB2101010 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffers + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * + * This function copies parts of a framebuffer to display memory and converts + * the color format during the process. The parameters @dst, @dst_pitch and + * @src refer to arrays. Each array must have at least as many entries as + * there are planes in @fb's format. Each entry stores the value for the + * format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for ARGB2101010 devices that don't support XRGB8888 + * natively. + */ +void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 4, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, + drm_fb_xrgb8888_to_argb2101010_line); +} +EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb2101010); + static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels) { u8 *dbuf8 = dbuf; @@ -696,8 +749,6 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d fb_format = DRM_FORMAT_XRGB8888; if (fb_format == DRM_FORMAT_ARGB2101010) fb_format = DRM_FORMAT_XRGB2101010; - if (dst_format == DRM_FORMAT_ARGB2101010) - dst_format = DRM_FORMAT_XRGB2101010; if (fb_format == dst_format) { drm_fb_memcpy(dst, dst_pitch, src, fb, clip); @@ -721,6 +772,9 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d } else if (dst_format == DRM_FORMAT_XRGB2101010) { drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip); return 0; + } else if (dst_format == DRM_FORMAT_ARGB2101010) { + drm_fb_xrgb8888_to_argb2101010(dst, dst_pitch, src, fb, clip); + return 0; } else if (dst_format == DRM_FORMAT_BGRX8888) { drm_fb_swab(dst, dst_pitch, src, fb, clip, false); return 0; diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index bc969413a412..de3aa252e8eb 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -47,6 +47,11 @@ struct convert_to_xrgb2101010_result { const u32 expected[TEST_BUF_SIZE]; }; +struct convert_to_argb2101010_result { + unsigned int dst_pitch; + const u32 expected[TEST_BUF_SIZE]; +}; + struct convert_xrgb8888_case { const char *name; unsigned int pitch; @@ -58,6 +63,7 @@ struct convert_xrgb8888_case { struct convert_to_rgb888_result rgb888_result; struct convert_to_argb8888_result argb8888_result; struct convert_to_xrgb2101010_result xrgb2101010_result; + struct convert_to_argb2101010_result argb2101010_result; }; static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { @@ -91,6 +97,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .dst_pitch = 0, .expected = { 0x3FF00000 }, }, + .argb2101010_result = { + .dst_pitch = 0, + .expected = { 0xFFF00000 }, + }, }, { .name = "single_pixel_clip_rectangle", @@ -125,6 +135,10 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .dst_pitch = 0, .expected = { 0x3FF00000 }, }, + .argb2101010_result = { + .dst_pitch = 0, + .expected = { 0xFFF00000 }, + }, }, { /* Well known colors: White, black, red, green, blue, magenta, @@ -201,6 +215,15 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0x3FFFFC00, 0x000FFFFF, }, }, + .argb2101010_result = { + .dst_pitch = 0, + .expected = { + 0xFFFFFFFF, 0xC0000000, + 0xFFF00000, 0xC00FFC00, + 0xC00003FF, 0xFFF003FF, + 0xFFFFFC00, 0xC00FFFFF, + }, + }, }, { /* Randomly picked colors. Full buffer within the clip area. */ @@ -268,6 +291,14 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0x2A20300C, 0x1B1705CD, 0x03844672, 0x00000000, 0x00000000, }, }, + .argb2101010_result = { + .dst_pitch = 20, + .expected = { + 0xC3844672, 0xC444D414, 0xEA20300C, 0x00000000, 0x00000000, + 0xDB1705CD, 0xC3844672, 0xC444D414, 0x00000000, 0x00000000, + 0xEA20300C, 0xDB1705CD, 0xC3844672, 0x00000000, 0x00000000, + }, + }, }, }; @@ -541,6 +572,37 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); } +static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test) +{ + const struct convert_xrgb8888_case *params = test->param_value; + const struct convert_to_argb2101010_result *result = ¶ms->argb2101010_result; + size_t dst_size; + u32 *buf = NULL; + __le32 *xrgb8888 = NULL; + struct iosys_map dst, src; + + struct drm_framebuffer fb = { + .format = drm_format_info(DRM_FORMAT_XRGB8888), + .pitches = { params->pitch, 0, 0 }, + }; + + dst_size = conversion_buf_size(DRM_FORMAT_ARGB2101010, + result->dst_pitch, ¶ms->clip); + KUNIT_ASSERT_GT(test, dst_size, 0); + + buf = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + iosys_map_set_vaddr(&dst, buf); + + xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888); + iosys_map_set_vaddr(&src, xrgb8888); + + drm_fb_xrgb8888_to_argb2101010(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); + buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); + KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); +} + static struct kunit_case drm_format_helper_test_cases[] = { KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_gray8, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params), @@ -548,6 +610,7 @@ static struct kunit_case drm_format_helper_test_cases[] = { KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params), + KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb2101010, convert_xrgb8888_gen_params), {} }; diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 3ce8129dfe43..10b2d19cdb66 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -39,6 +39,9 @@ void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_ void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); +void drm_fb_xrgb8888_to_argb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip); void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); -- cgit v1.2.3 From 10cd592e639edcea50d781a07edcf3470d1f222e Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Jan 2023 12:29:23 +0100 Subject: drm/format-helper: Add conversion from XRGB8888 to 15-bit RGB555 formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add conversion from XRGB8888 to XRGB1555, ARGB1555 and RGBA5551, which are the formats currently supported by the simplefb infrastructure. The new helpers allow the output of XRGB8888 framebuffers to firmware scanout buffers in one of the 15-bit formats. v3: * use __le* for destination buffers (Jose, kernel test robot) v2: * test 15-bit results with local endianness (Jose) Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Reviewed-by: José Expósito Link: https://patchwork.freedesktop.org/patch/msgid/20230102112927.26565-10-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 164 +++++++++++++++++++++ drivers/gpu/drm/tests/drm_format_helper_test.c | 189 +++++++++++++++++++++++++ include/drm/drm_format_helper.h | 9 ++ 3 files changed, 362 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 33780c9183bb..d631627e6c39 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -396,6 +396,161 @@ void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pi } EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565); +static void drm_fb_xrgb8888_to_xrgb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + __le16 *dbuf16 = dbuf; + const __le32 *sbuf32 = sbuf; + unsigned int x; + u16 val16; + u32 pix; + + for (x = 0; x < pixels; x++) { + pix = le32_to_cpu(sbuf32[x]); + val16 = ((pix & 0x00f80000) >> 9) | + ((pix & 0x0000f800) >> 6) | + ((pix & 0x000000f8) >> 3); + dbuf16[x] = cpu_to_le16(val16); + } +} + +/** + * drm_fb_xrgb8888_to_xrgb1555 - Convert XRGB8888 to XRGB1555 clip buffer + * @dst: Array of XRGB1555 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * + * This function copies parts of a framebuffer to display memory and converts + * the color format during the process. The parameters @dst, @dst_pitch and + * @src refer to arrays. Each array must have at least as many entries as + * there are planes in @fb's format. Each entry stores the value for the + * format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for XRGB1555 devices that don't support + * XRGB8888 natively. + */ +void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 2, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, + drm_fb_xrgb8888_to_xrgb1555_line); +} +EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb1555); + +static void drm_fb_xrgb8888_to_argb1555_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + __le16 *dbuf16 = dbuf; + const __le32 *sbuf32 = sbuf; + unsigned int x; + u16 val16; + u32 pix; + + for (x = 0; x < pixels; x++) { + pix = le32_to_cpu(sbuf32[x]); + val16 = BIT(15) | /* set alpha bit */ + ((pix & 0x00f80000) >> 9) | + ((pix & 0x0000f800) >> 6) | + ((pix & 0x000000f8) >> 3); + dbuf16[x] = cpu_to_le16(val16); + } +} + +/** + * drm_fb_xrgb8888_to_argb1555 - Convert XRGB8888 to ARGB1555 clip buffer + * @dst: Array of ARGB1555 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * + * This function copies parts of a framebuffer to display memory and converts + * the color format during the process. The parameters @dst, @dst_pitch and + * @src refer to arrays. Each array must have at least as many entries as + * there are planes in @fb's format. Each entry stores the value for the + * format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for ARGB1555 devices that don't support + * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion. + */ +void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 2, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, + drm_fb_xrgb8888_to_argb1555_line); +} +EXPORT_SYMBOL(drm_fb_xrgb8888_to_argb1555); + +static void drm_fb_xrgb8888_to_rgba5551_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + __le16 *dbuf16 = dbuf; + const __le32 *sbuf32 = sbuf; + unsigned int x; + u16 val16; + u32 pix; + + for (x = 0; x < pixels; x++) { + pix = le32_to_cpu(sbuf32[x]); + val16 = ((pix & 0x00f80000) >> 8) | + ((pix & 0x0000f800) >> 5) | + ((pix & 0x000000f8) >> 2) | + BIT(0); /* set alpha bit */ + dbuf16[x] = cpu_to_le16(val16); + } +} + +/** + * drm_fb_xrgb8888_to_rgba5551 - Convert XRGB8888 to RGBA5551 clip buffer + * @dst: Array of RGBA5551 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * + * This function copies parts of a framebuffer to display memory and converts + * the color format during the process. The parameters @dst, @dst_pitch and + * @src refer to arrays. Each array must have at least as many entries as + * there are planes in @fb's format. Each entry stores the value for the + * format's respective color plane at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for RGBA5551 devices that don't support + * XRGB8888 natively. It sets an opaque alpha channel as part of the conversion. + */ +void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 2, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, + drm_fb_xrgb8888_to_rgba5551_line); +} +EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgba5551); + static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels) { u8 *dbuf8 = dbuf; @@ -763,6 +918,15 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d if (dst_format == DRM_FORMAT_RGB565) { drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false); return 0; + } else if (dst_format == DRM_FORMAT_XRGB1555) { + drm_fb_xrgb8888_to_xrgb1555(dst, dst_pitch, src, fb, clip); + return 0; + } else if (dst_format == DRM_FORMAT_ARGB1555) { + drm_fb_xrgb8888_to_argb1555(dst, dst_pitch, src, fb, clip); + return 0; + } else if (dst_format == DRM_FORMAT_RGBA5551) { + drm_fb_xrgb8888_to_rgba5551(dst, dst_pitch, src, fb, clip); + return 0; } else if (dst_format == DRM_FORMAT_RGB888) { drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip); return 0; diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index de3aa252e8eb..f71dc0fe08a1 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -32,6 +32,21 @@ struct convert_to_rgb565_result { const u16 expected_swab[TEST_BUF_SIZE]; }; +struct convert_to_xrgb1555_result { + unsigned int dst_pitch; + const u16 expected[TEST_BUF_SIZE]; +}; + +struct convert_to_argb1555_result { + unsigned int dst_pitch; + const u16 expected[TEST_BUF_SIZE]; +}; + +struct convert_to_rgba5551_result { + unsigned int dst_pitch; + const u16 expected[TEST_BUF_SIZE]; +}; + struct convert_to_rgb888_result { unsigned int dst_pitch; const u8 expected[TEST_BUF_SIZE]; @@ -60,6 +75,9 @@ struct convert_xrgb8888_case { struct convert_to_gray8_result gray8_result; struct convert_to_rgb332_result rgb332_result; struct convert_to_rgb565_result rgb565_result; + struct convert_to_xrgb1555_result xrgb1555_result; + struct convert_to_argb1555_result argb1555_result; + struct convert_to_rgba5551_result rgba5551_result; struct convert_to_rgb888_result rgb888_result; struct convert_to_argb8888_result argb8888_result; struct convert_to_xrgb2101010_result xrgb2101010_result; @@ -85,6 +103,18 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .expected = { 0xF800 }, .expected_swab = { 0x00F8 }, }, + .xrgb1555_result = { + .dst_pitch = 0, + .expected = { 0x7C00 }, + }, + .argb1555_result = { + .dst_pitch = 0, + .expected = { 0xFC00 }, + }, + .rgba5551_result = { + .dst_pitch = 0, + .expected = { 0xF801 }, + }, .rgb888_result = { .dst_pitch = 0, .expected = { 0x00, 0x00, 0xFF }, @@ -123,6 +153,18 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .expected = { 0xF800 }, .expected_swab = { 0x00F8 }, }, + .xrgb1555_result = { + .dst_pitch = 0, + .expected = { 0x7C00 }, + }, + .argb1555_result = { + .dst_pitch = 0, + .expected = { 0xFC00 }, + }, + .rgba5551_result = { + .dst_pitch = 0, + .expected = { 0xF801 }, + }, .rgb888_result = { .dst_pitch = 0, .expected = { 0x00, 0x00, 0xFF }, @@ -188,6 +230,33 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0xE0FF, 0xFF07, }, }, + .xrgb1555_result = { + .dst_pitch = 0, + .expected = { + 0x7FFF, 0x0000, + 0x7C00, 0x03E0, + 0x001F, 0x7C1F, + 0x7FE0, 0x03FF, + }, + }, + .argb1555_result = { + .dst_pitch = 0, + .expected = { + 0xFFFF, 0x8000, + 0xFC00, 0x83E0, + 0x801F, 0xFC1F, + 0xFFE0, 0x83FF, + }, + }, + .rgba5551_result = { + .dst_pitch = 0, + .expected = { + 0xFFFF, 0x0001, + 0xF801, 0x07C1, + 0x003F, 0xF83F, + 0xFFC1, 0x07FF, + }, + }, .rgb888_result = { .dst_pitch = 0, .expected = { @@ -264,6 +333,30 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { 0x00A8, 0x8E6B, 0x330A, 0x0000, 0x0000, }, }, + .xrgb1555_result = { + .dst_pitch = 10, + .expected = { + 0x0513, 0x0920, 0x5400, 0x0000, 0x0000, + 0x35CE, 0x0513, 0x0920, 0x0000, 0x0000, + 0x5400, 0x35CE, 0x0513, 0x0000, 0x0000, + }, + }, + .argb1555_result = { + .dst_pitch = 10, + .expected = { + 0x8513, 0x8920, 0xD400, 0x0000, 0x0000, + 0xB5CE, 0x8513, 0x8920, 0x0000, 0x0000, + 0xD400, 0xB5CE, 0x8513, 0x0000, 0x0000, + }, + }, + .rgba5551_result = { + .dst_pitch = 10, + .expected = { + 0x0A27, 0x1241, 0xA801, 0x0000, 0x0000, + 0x6B9D, 0x0A27, 0x1241, 0x0000, 0x0000, + 0xA801, 0x6B9D, 0x0A27, 0x0000, 0x0000, + }, + }, .rgb888_result = { .dst_pitch = 15, .expected = { @@ -476,6 +569,99 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test) KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected_swab, dst_size), 0); } +static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test) +{ + const struct convert_xrgb8888_case *params = test->param_value; + const struct convert_to_xrgb1555_result *result = ¶ms->xrgb1555_result; + size_t dst_size; + u16 *buf = NULL; + __le32 *xrgb8888 = NULL; + struct iosys_map dst, src; + + struct drm_framebuffer fb = { + .format = drm_format_info(DRM_FORMAT_XRGB8888), + .pitches = { params->pitch, 0, 0 }, + }; + + dst_size = conversion_buf_size(DRM_FORMAT_XRGB1555, result->dst_pitch, + ¶ms->clip); + KUNIT_ASSERT_GT(test, dst_size, 0); + + buf = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + iosys_map_set_vaddr(&dst, buf); + + xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888); + iosys_map_set_vaddr(&src, xrgb8888); + + drm_fb_xrgb8888_to_xrgb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); + buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); + KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); +} + +static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test) +{ + const struct convert_xrgb8888_case *params = test->param_value; + const struct convert_to_argb1555_result *result = ¶ms->argb1555_result; + size_t dst_size; + u16 *buf = NULL; + __le32 *xrgb8888 = NULL; + struct iosys_map dst, src; + + struct drm_framebuffer fb = { + .format = drm_format_info(DRM_FORMAT_XRGB8888), + .pitches = { params->pitch, 0, 0 }, + }; + + dst_size = conversion_buf_size(DRM_FORMAT_ARGB1555, result->dst_pitch, + ¶ms->clip); + KUNIT_ASSERT_GT(test, dst_size, 0); + + buf = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + iosys_map_set_vaddr(&dst, buf); + + xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888); + iosys_map_set_vaddr(&src, xrgb8888); + + drm_fb_xrgb8888_to_argb1555(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); + buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); + KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); +} + +static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test) +{ + const struct convert_xrgb8888_case *params = test->param_value; + const struct convert_to_rgba5551_result *result = ¶ms->rgba5551_result; + size_t dst_size; + u16 *buf = NULL; + __le32 *xrgb8888 = NULL; + struct iosys_map dst, src; + + struct drm_framebuffer fb = { + .format = drm_format_info(DRM_FORMAT_XRGB8888), + .pitches = { params->pitch, 0, 0 }, + }; + + dst_size = conversion_buf_size(DRM_FORMAT_RGBA5551, result->dst_pitch, + ¶ms->clip); + KUNIT_ASSERT_GT(test, dst_size, 0); + + buf = kunit_kzalloc(test, dst_size, GFP_KERNEL); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buf); + iosys_map_set_vaddr(&dst, buf); + + xrgb8888 = cpubuf_to_le32(test, params->xrgb8888, TEST_BUF_SIZE); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, xrgb8888); + iosys_map_set_vaddr(&src, xrgb8888); + + drm_fb_xrgb8888_to_rgba5551(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip); + buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); + KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0); +} + static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test) { const struct convert_xrgb8888_case *params = test->param_value; @@ -607,6 +793,9 @@ static struct kunit_case drm_format_helper_test_cases[] = { KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_gray8, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb332, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb565, convert_xrgb8888_gen_params), + KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb1555, convert_xrgb8888_gen_params), + KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb1555, convert_xrgb8888_gen_params), + KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgba5551, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_rgb888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_argb8888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xrgb2101010, convert_xrgb8888_gen_params), diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 10b2d19cdb66..2d04f5863722 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -30,6 +30,15 @@ void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, bool swab); +void drm_fb_xrgb8888_to_xrgb1555(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip); +void drm_fb_xrgb8888_to_argb1555(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip); +void drm_fb_xrgb8888_to_rgba5551(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip); void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip); -- cgit v1.2.3 From 29fca6d56d76363368d012e18b5631340cfcd69c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Mon, 2 Jan 2023 12:29:26 +0100 Subject: drm/format-helper: Simplify drm_fb_build_fourcc_list() The DRM helper drm_fb_build_fourcc_list() creates a list of color formats for primary planes of the generic drivers. Simplify the helper: - It used to mix and filter native and emulated formats as provided by the driver. Now the only emulated format is XRGB8888, which is required as fallback by legacy software. Drop support for emulating any other formats. - Also convert alpha formats to their non-alpha counterparts. Generic drivers don't support primary planes with alpha formats and some DTs incorrectly advertise alpha channels for non-alpha hardware. So only export non-alpha formats for primary planes. With the simplified helper, scrap format lists of the affected generic drivers. All they need is the firmware buffer's native format, from which the helper creates the list of color formats. Signed-off-by: Thomas Zimmermann Reviewed-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20230102112927.26565-13-tzimmermann@suse.de --- drivers/gpu/drm/drm_format_helper.c | 112 ++++++++++++++++++------------------ drivers/gpu/drm/tiny/ofdrm.c | 20 ------- drivers/gpu/drm/tiny/simpledrm.c | 21 ------- include/drm/drm_format_helper.h | 1 - 4 files changed, 57 insertions(+), 97 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index d631627e6c39..0523f81e2445 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -1070,6 +1070,39 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc } EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); +static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc) +{ + /* only handle formats with depth != 0 and alpha channel */ + switch (fourcc) { + case DRM_FORMAT_ARGB1555: + return DRM_FORMAT_XRGB1555; + case DRM_FORMAT_ABGR1555: + return DRM_FORMAT_XBGR1555; + case DRM_FORMAT_RGBA5551: + return DRM_FORMAT_RGBX5551; + case DRM_FORMAT_BGRA5551: + return DRM_FORMAT_BGRX5551; + case DRM_FORMAT_ARGB8888: + return DRM_FORMAT_XRGB8888; + case DRM_FORMAT_ABGR8888: + return DRM_FORMAT_XBGR8888; + case DRM_FORMAT_RGBA8888: + return DRM_FORMAT_RGBX8888; + case DRM_FORMAT_BGRA8888: + return DRM_FORMAT_BGRX8888; + case DRM_FORMAT_ARGB2101010: + return DRM_FORMAT_XRGB2101010; + case DRM_FORMAT_ABGR2101010: + return DRM_FORMAT_XBGR2101010; + case DRM_FORMAT_RGBA1010102: + return DRM_FORMAT_RGBX1010102; + case DRM_FORMAT_BGRA1010102: + return DRM_FORMAT_BGRX1010102; + } + + return fourcc; +} + static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc) { const uint32_t *fourccs_end = fourccs + nfourccs; @@ -1082,73 +1115,48 @@ static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t return false; } -static const uint32_t conv_from_xrgb8888[] = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_ARGB2101010, - DRM_FORMAT_RGB565, - DRM_FORMAT_RGB888, -}; - -static const uint32_t conv_from_rgb565_888[] = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, -}; - -static bool is_conversion_supported(uint32_t from, uint32_t to) -{ - switch (from) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - return is_listed_fourcc(conv_from_xrgb8888, ARRAY_SIZE(conv_from_xrgb8888), to); - case DRM_FORMAT_RGB565: - case DRM_FORMAT_RGB888: - return is_listed_fourcc(conv_from_rgb565_888, ARRAY_SIZE(conv_from_rgb565_888), to); - case DRM_FORMAT_XRGB2101010: - return to == DRM_FORMAT_ARGB2101010; - case DRM_FORMAT_ARGB2101010: - return to == DRM_FORMAT_XRGB2101010; - default: - return false; - } -} - /** * drm_fb_build_fourcc_list - Filters a list of supported color formats against * the device's native formats * @dev: DRM device * @native_fourccs: 4CC codes of natively supported color formats * @native_nfourccs: The number of entries in @native_fourccs - * @driver_fourccs: 4CC codes of all driver-supported color formats - * @driver_nfourccs: The number of entries in @driver_fourccs * @fourccs_out: Returns 4CC codes of supported color formats * @nfourccs_out: The number of available entries in @fourccs_out * * This function create a list of supported color format from natively - * supported formats and the emulated formats. + * supported formats and additional emulated formats. * At a minimum, most userspace programs expect at least support for * XRGB8888 on the primary plane. Devices that have to emulate the * format, and possibly others, can use drm_fb_build_fourcc_list() to * create a list of supported color formats. The returned list can * be handed over to drm_universal_plane_init() et al. Native formats - * will go before emulated formats. Other heuristics might be applied + * will go before emulated formats. Native formats with alpha channel + * will be replaced by such without, as primary planes usually don't + * support alpha. Other heuristics might be applied * to optimize the order. Formats near the beginning of the list are - * usually preferred over formats near the end of the list. Formats - * without conversion helpers will be skipped. New drivers should only - * pass in XRGB8888 and avoid exposing additional emulated formats. + * usually preferred over formats near the end of the list. * * Returns: * The number of color-formats 4CC codes returned in @fourccs_out. */ size_t drm_fb_build_fourcc_list(struct drm_device *dev, const u32 *native_fourccs, size_t native_nfourccs, - const u32 *driver_fourccs, size_t driver_nfourccs, u32 *fourccs_out, size_t nfourccs_out) { + /* + * XRGB8888 is the default fallback format for most of userspace + * and it's currently the only format that should be emulated for + * the primary plane. Only if there's ever another default fallback, + * it should be added here. + */ + static const uint32_t extra_fourccs[] = { + DRM_FORMAT_XRGB8888, + }; + static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs); + u32 *fourccs = fourccs_out; const u32 *fourccs_end = fourccs_out + nfourccs_out; - uint32_t native_format = 0; size_t i; /* @@ -1156,7 +1164,12 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev, */ for (i = 0; i < native_nfourccs; ++i) { - u32 fourcc = native_fourccs[i]; + /* + * Several DTs, boot loaders and firmware report native + * alpha formats that are non-alpha formats instead. So + * replace alpha formats by non-alpha formats. + */ + u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]); if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { continue; /* skip duplicate entries */ @@ -1167,14 +1180,6 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev, drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); - /* - * There should only be one native format with the current API. - * This API needs to be refactored to correctly support arbitrary - * sets of native formats, since it needs to report which native - * format to use for each emulated format. - */ - if (!native_format) - native_format = fourcc; *fourccs = fourcc; ++fourccs; } @@ -1183,17 +1188,14 @@ size_t drm_fb_build_fourcc_list(struct drm_device *dev, * The extra formats, emulated by the driver, go second. */ - for (i = 0; (i < driver_nfourccs) && (fourccs < fourccs_end); ++i) { - u32 fourcc = driver_fourccs[i]; + for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) { + u32 fourcc = extra_fourccs[i]; if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { continue; /* skip duplicate and native entries */ } else if (fourccs == fourccs_end) { drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); continue; /* end of available output buffer */ - } else if (!is_conversion_supported(fourcc, native_format)) { - drm_dbg_kms(dev, "Unsupported emulated format %p4cc\n", &fourcc); - continue; /* format is not supported for conversion */ } drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c index 33eefeba437c..39c5fd463fec 100644 --- a/drivers/gpu/drm/tiny/ofdrm.c +++ b/drivers/gpu/drm/tiny/ofdrm.c @@ -754,24 +754,6 @@ static void ofdrm_crtc_state_destroy(struct ofdrm_crtc_state *ofdrm_crtc_state) kfree(ofdrm_crtc_state); } -/* - * Support all formats of OF display and maybe more; in order - * of preference. The display's update function will do any - * conversion necessary. - * - * TODO: Add blit helpers for remaining formats and uncomment - * constants. - */ -static const uint32_t ofdrm_primary_plane_formats[] = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB565, - //DRM_FORMAT_XRGB1555, - //DRM_FORMAT_C8, - /* Big-endian formats below */ - DRM_FORMAT_BGRX8888, - DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN, -}; - static const uint64_t ofdrm_primary_plane_format_modifiers[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID @@ -1290,8 +1272,6 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, /* Primary plane */ nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - ofdrm_primary_plane_formats, - ARRAY_SIZE(ofdrm_primary_plane_formats), odev->formats, ARRAY_SIZE(odev->formats)); primary_plane = &odev->primary_plane; diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 30e928d627e8..7355617f38d3 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -446,25 +446,6 @@ static int simpledrm_device_init_regulators(struct simpledrm_device *sdev) * Modesetting */ -/* - * Support all formats of simplefb and maybe more; in order - * of preference. The display's update function will do any - * conversion necessary. - * - * TODO: Add blit helpers for remaining formats and uncomment - * constants. - */ -static const uint32_t simpledrm_primary_plane_formats[] = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGB565, - //DRM_FORMAT_XRGB1555, - //DRM_FORMAT_ARGB1555, - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_ARGB2101010, -}; - static const uint64_t simpledrm_primary_plane_format_modifiers[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID @@ -745,8 +726,6 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, /* Primary plane */ nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - simpledrm_primary_plane_formats, - ARRAY_SIZE(simpledrm_primary_plane_formats), sdev->formats, ARRAY_SIZE(sdev->formats)); primary_plane = &sdev->primary_plane; diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 2d04f5863722..291deb09475b 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -65,7 +65,6 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc size_t drm_fb_build_fourcc_list(struct drm_device *dev, const u32 *native_fourccs, size_t native_nfourccs, - const u32 *extra_fourccs, size_t extra_nfourccs, u32 *fourccs_out, size_t nfourccs_out); #endif /* __LINUX_DRM_FORMAT_HELPER_H */ -- cgit v1.2.3 From b357e7ac1b7349befaeded273b775c7af23a538b Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 23 Nov 2022 20:24:37 +0100 Subject: drm/fourcc: Document open source user waiver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's a bit a FAQ, and we really can't claim to be the authoritative source for allocating these numbers used in many standard extensions if we tell closed source or vendor stacks in general to go away. Iirc this was already clarified in some vulkan discussions, but I can't find that anywhere anymore. At least not in a public link. Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: David Airlie Cc: Daniel Vetter Cc: Alex Deucher Cc: Daniel Stone Cc: Bas Nieuwenhuizen Cc: Jason Ekstrand Cc: Neil Trevett Acked-by: Daniel Stone Acked-by: Maxime Ripard Acked-by: David Airlie Acked-by: Marek Olšák Acked-by: Bas Nieuwenhuizen Acked-by: Jason Ekstrand Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20221123192437.1065826-1-daniel.vetter@ffwll.ch --- include/uapi/drm/drm_fourcc.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index bc056f2d537d..de703c6be969 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -88,6 +88,18 @@ extern "C" { * * The authoritative list of format modifier codes is found in * `include/uapi/drm/drm_fourcc.h` + * + * Open Source User Waiver + * ----------------------- + * + * Because this is the authoritative source for pixel formats and modifiers + * referenced by GL, Vulkan extensions and other standards and hence used both + * by open source and closed source driver stacks, the usual requirement for an + * upstream in-kernel or open source userspace user does not apply. + * + * To ensure, as much as feasible, compatibility across stacks and avoid + * confusion with incompatible enumerations stakeholders for all relevant driver + * stacks should approve additions. */ #define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \ -- cgit v1.2.3 From c8268795c9a9cc7be50f78d4502fad83a2a4f8df Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 2 Nov 2022 21:07:00 +0300 Subject: drm/probe-helper: enable and disable HPD on connectors Introduce two drm_connector_helper_funcs: enable_hpd() and disable_hpd(). They are called by drm_kms_helper_poll_enable() and drm_kms_helper_poll_disable() (and thus drm_kms_helper_poll_init() and drm_kms_helper_poll_fini()) respectively. This allows DRM drivers to rely on drm_kms_helper_poll for enabling and disabling HPD detection rather than doing that manually. Signed-off-by: Dmitry Baryshkov Reviewed-by: Tomi Valkeinen Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20221102180705.459294-3-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/drm_probe_helper.c | 19 +++++++++++++++++++ include/drm/drm_modeset_helper_vtables.h | 22 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'include') diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index d07ad4c5696b..7973f2589ced 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -250,6 +250,12 @@ void drm_kms_helper_poll_enable(struct drm_device *dev) drm_connector_list_iter_begin(dev, &conn_iter); drm_for_each_connector_iter(connector, &conn_iter) { + const struct drm_connector_helper_funcs *funcs = + connector->helper_private; + + if (funcs && funcs->enable_hpd) + funcs->enable_hpd(connector); + if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) poll = true; @@ -804,12 +810,25 @@ EXPORT_SYMBOL(drm_kms_helper_is_poll_worker); static void drm_kms_helper_poll_disable_fini(struct drm_device *dev, bool fini) { + struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + if (!dev->mode_config.poll_enabled) return; if (fini) dev->mode_config.poll_enabled = false; + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + const struct drm_connector_helper_funcs *funcs = + connector->helper_private; + + if (funcs && funcs->disable_hpd) + funcs->disable_hpd(connector); + } + drm_connector_list_iter_end(&conn_iter); + cancel_delayed_work_sync(&dev->mode_config.output_poll_work); } diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h index d9f2254a039a..77a540ad7dcd 100644 --- a/include/drm/drm_modeset_helper_vtables.h +++ b/include/drm/drm_modeset_helper_vtables.h @@ -1143,6 +1143,28 @@ struct drm_connector_helper_funcs { */ void (*cleanup_writeback_job)(struct drm_writeback_connector *connector, struct drm_writeback_job *job); + + /** + * @enable_hpd: + * + * Enable hot-plug detection for the connector. + * + * This operation is optional. + * + * This callback is used by the drm_kms_helper_poll_enable() helpers. + */ + void (*enable_hpd)(struct drm_connector *connector); + + /** + * @disable_hpd: + * + * Disable hot-plug detection for the connector. + * + * This operation is optional. + * + * This callback is used by the drm_kms_helper_poll_disable() helpers. + */ + void (*disable_hpd)(struct drm_connector *connector); }; /** -- cgit v1.2.3 From 4c00ac500d0edd1a6730c4e8293834a694c1b304 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 2 Nov 2022 21:07:05 +0300 Subject: drm/bridge_connector: drop drm_bridge_connector_en/disable_hpd() Now as all drivers stopped calling drm_bridge_connector_enable_hpd() and drm_bridge_connector_disable_hpd() it is safe to remove them complelely. Rename our internal helpers to remove the underscore prefix. Signed-off-by: Dmitry Baryshkov Reviewed-by: Tomi Valkeinen Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20221102180705.459294-8-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/drm_bridge_connector.c | 33 ++++----------------------------- include/drm/drm_bridge_connector.h | 2 -- 2 files changed, 4 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c index 0e13bc87a6ac..19ae4a177ac3 100644 --- a/drivers/gpu/drm/drm_bridge_connector.c +++ b/drivers/gpu/drm/drm_bridge_connector.c @@ -128,19 +128,7 @@ static void drm_bridge_connector_hpd_cb(void *cb_data, drm_kms_helper_hotplug_event(dev); } -/** - * drm_bridge_connector_enable_hpd - Enable hot-plug detection for the connector - * @connector: The DRM bridge connector - * - * This function enables hot-plug detection for the given bridge connector. - * This is typically used by display drivers in their resume handler. - */ -void drm_bridge_connector_enable_hpd(struct drm_connector *connector) -{ -} -EXPORT_SYMBOL_GPL(drm_bridge_connector_enable_hpd); - -static void _drm_bridge_connector_enable_hpd(struct drm_connector *connector) +static void drm_bridge_connector_enable_hpd(struct drm_connector *connector) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); @@ -151,20 +139,7 @@ static void _drm_bridge_connector_enable_hpd(struct drm_connector *connector) bridge_connector); } -/** - * drm_bridge_connector_disable_hpd - Disable hot-plug detection for the - * connector - * @connector: The DRM bridge connector - * - * This function disables hot-plug detection for the given bridge connector. - * This is typically used by display drivers in their suspend handler. - */ -void drm_bridge_connector_disable_hpd(struct drm_connector *connector) -{ -} -EXPORT_SYMBOL_GPL(drm_bridge_connector_disable_hpd); - -static void _drm_bridge_connector_disable_hpd(struct drm_connector *connector) +static void drm_bridge_connector_disable_hpd(struct drm_connector *connector) { struct drm_bridge_connector *bridge_connector = to_drm_bridge_connector(connector); @@ -313,8 +288,8 @@ static int drm_bridge_connector_get_modes(struct drm_connector *connector) static const struct drm_connector_helper_funcs drm_bridge_connector_helper_funcs = { .get_modes = drm_bridge_connector_get_modes, /* No need for .mode_valid(), the bridges are checked by the core. */ - .enable_hpd = _drm_bridge_connector_enable_hpd, - .disable_hpd = _drm_bridge_connector_disable_hpd, + .enable_hpd = drm_bridge_connector_enable_hpd, + .disable_hpd = drm_bridge_connector_disable_hpd, }; /* ----------------------------------------------------------------------------- diff --git a/include/drm/drm_bridge_connector.h b/include/drm/drm_bridge_connector.h index 33f6c3bbdb4a..69630815fb09 100644 --- a/include/drm/drm_bridge_connector.h +++ b/include/drm/drm_bridge_connector.h @@ -10,8 +10,6 @@ struct drm_connector; struct drm_device; struct drm_encoder; -void drm_bridge_connector_enable_hpd(struct drm_connector *connector); -void drm_bridge_connector_disable_hpd(struct drm_connector *connector); struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, struct drm_encoder *encoder); -- cgit v1.2.3 From 51d3c0e7dc3cf1dd91c34b0f9bdadda310c7ed5b Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 2 Jan 2023 21:25:41 +0100 Subject: drm/mipi-dsi: Fix mipi_dsi_dcs_write_seq() macro definition format Change made using a `clang-format -i include/drm/drm_mipi_dsi.h` command. Suggested-by: Sam Ravnborg Signed-off-by: Javier Martinez Canillas Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20230102202542.3494677-1-javierm@redhat.com --- include/drm/drm_mipi_dsi.h | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 20b21b577dea..e9d1e8a7fc7e 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -303,15 +303,18 @@ int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, * @cmd: Command * @seq: buffer containing data to be transmitted */ -#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...) do { \ - static const u8 d[] = { cmd, seq }; \ - struct device *dev = &dsi->dev; \ - int ret; \ - ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \ - if (ret < 0) { \ - dev_err_ratelimited(dev, "sending command %#02x failed: %d\n", cmd, ret); \ - return ret; \ - } \ +#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...) \ + do { \ + static const u8 d[] = { cmd, seq }; \ + struct device *dev = &dsi->dev; \ + int ret; \ + ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \ + if (ret < 0) { \ + dev_err_ratelimited( \ + dev, "sending command %#02x failed: %d\n", \ + cmd, ret); \ + return ret; \ + } \ } while (0) /** -- cgit v1.2.3 From a9015ce593204f487bcb3069c5908155ccc59f30 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Mon, 2 Jan 2023 21:25:42 +0100 Subject: drm/mipi-dsi: Add a mipi_dsi_dcs_write_seq() macro Many panel drivers define dsi_dcs_write_seq() and dsi_generic_write_seq() macros to send DCS commands and generic write packets respectively, with the payload specified as a list of parameters instead of using arrays. There's already a macro for the former, introduced by commit 2a9e9daf75231 ("drm/mipi-dsi: Introduce mipi_dsi_dcs_write_seq macro") so drivers can be changed to use that. But there isn't one yet for the latter, let's add it. Signed-off-by: Javier Martinez Canillas Reviewed-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20230102202542.3494677-2-javierm@redhat.com --- include/drm/drm_mipi_dsi.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'include') diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index e9d1e8a7fc7e..4f503d99f668 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -297,6 +297,24 @@ int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi, int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, u16 *brightness); +/** + * mipi_dsi_generic_write_seq - transmit data using a generic write packet + * @dsi: DSI peripheral device + * @seq: buffer containing the payload + */ +#define mipi_dsi_generic_write_seq(dsi, seq...) \ + do { \ + static const u8 d[] = { seq }; \ + struct device *dev = &dsi->dev; \ + int ret; \ + ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \ + if (ret < 0) { \ + dev_err_ratelimited(dev, "transmit data failed: %d\n", \ + ret); \ + return ret; \ + } \ + } while (0) + /** * mipi_dsi_dcs_write_seq - transmit a DCS command with payload * @dsi: DSI peripheral device -- cgit v1.2.3 From 5855366f7d21af8a24d92270c11350982de1d671 Mon Sep 17 00:00:00 2001 From: Maíra Canal Date: Thu, 5 Jan 2023 16:30:39 -0300 Subject: drm/debugfs: add descriptions to struct parameters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The structs drm_debugfs_info and drm_debugfs_entry don't have descriptions for their parameters, which is causing the following warnings: include/drm/drm_debugfs.h:93: warning: Function parameter or member 'name' not described in 'drm_debugfs_info' include/drm/drm_debugfs.h:93: warning: Function parameter or member 'show' not described in 'drm_debugfs_info' include/drm/drm_debugfs.h:93: warning: Function parameter or member 'driver_features' not described in 'drm_debugfs_info' include/drm/drm_debugfs.h:93: warning: Function parameter or member 'data' not described in 'drm_debugfs_info' include/drm/drm_debugfs.h:105: warning: Function parameter or member 'dev' not described in 'drm_debugfs_entry' include/drm/drm_debugfs.h:105: warning: Function parameter or member 'file' not described in 'drm_debugfs_entry' include/drm/drm_debugfs.h:105: warning: Function parameter or member 'list' not described in 'drm_debugfs_entry' Therefore, fix the warnings by adding descriptions to all struct parameters. Reported-by: Stephen Rothwell Signed-off-by: Maíra Canal Reviewed-by: Daniel Vetter Signed-off-by: Maíra Canal Link: https://patchwork.freedesktop.org/patch/msgid/20230105193039.287677-2-mcanal@igalia.com --- include/drm/drm_debugfs.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'include') diff --git a/include/drm/drm_debugfs.h b/include/drm/drm_debugfs.h index 53b7297260a5..7616f457ce70 100644 --- a/include/drm/drm_debugfs.h +++ b/include/drm/drm_debugfs.h @@ -86,9 +86,22 @@ struct drm_info_node { * core. */ struct drm_debugfs_info { + /** @name: File name */ const char *name; + + /** + * @show: + * + * Show callback. &seq_file->private will be set to the &struct + * drm_debugfs_entry corresponding to the instance of this info + * on a given &struct drm_device. + */ int (*show)(struct seq_file*, void*); + + /** @driver_features: Required driver features for this entry. */ u32 driver_features; + + /** @data: Driver-private data, should not be device-specific. */ void *data; }; @@ -99,8 +112,13 @@ struct drm_debugfs_info { * drm_debugfs_info on a &struct drm_device. */ struct drm_debugfs_entry { + /** @dev: &struct drm_device for this node. */ struct drm_device *dev; + + /** @file: Template for this node. */ struct drm_debugfs_info file; + + /** @list: Linked list of all device nodes. */ struct list_head list; }; -- cgit v1.2.3 From 99845faae7099cd704ebf67514c1157c26960a26 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 9 Jan 2023 17:46:04 +0100 Subject: drm: document better that drivers shouldn't use drm_minor directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation for struct drm_minor already states this, but that's not always that easy to find. Also due to historical reasons we still have the minor-centric interfaces (like drm_debugfs_create_files), but since this is now getting fixed we can put a few more pointers in place as to how this should be done ideally. Note that debugfs isn't there yet for all cases (debugfs files on kms objects like crtc/connector aren't supported, neither debugfs files with full fops), so the debugfs side of this is still rather aspirational and more for new users than converting everything existing. todo.rst covers the additional work needed already. Motivated by some discussion with Rodrigo on irc about how drm/xe should lay out its sysfs interfaces. v2: Make the debugfs situation clearer in the commit message, but don't elaborate more in the actual kerneldoc to avoid distracting from the main message around sysfs (Jani) Also fix some typos. Acked-by: Rodrigo Vivi Reviewed-by: Melissa Wen Reviewed-by: Maíra Canal Acked-by: Maxime Ripard Acked-by: Jani Nikula Cc: Rodrigo Vivi Cc: Wambui Karuga Cc: Maíra Canal Cc: Maxime Ripard Cc: Melissa Wen Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20230109164604.3860862-1-daniel.vetter@ffwll.ch --- include/drm/drm_device.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index fa6af1d57929..282a171164ee 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -87,10 +87,23 @@ struct drm_device { */ void *dev_private; - /** @primary: Primary node */ + /** + * @primary: + * + * Primary node. Drivers should not interact with this + * directly. debugfs interfaces can be registered with + * drm_debugfs_add_file(), and sysfs should be directly added on the + * hardware (and not character device node) struct device @dev. + */ struct drm_minor *primary; - /** @render: Render node */ + /** + * @render: + * + * Render node. Drivers should not interact with this directly ever. + * Drivers should not expose any additional interfaces in debugfs or + * sysfs on this node. + */ struct drm_minor *render; /** -- cgit v1.2.3 From cf8698df3a7d7f46975b9d8bf79d310e17afbf4f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Thu, 12 Jan 2023 14:38:58 +0100 Subject: drm/nouveau: Remove support for legacy contexts/buffers Remove nouveau's support for legacy contexts and buffers. It was required by libdrm earlier than 2.4.33, released in March 2012. A previous attempt in 2013 to remove the functionality [1] had to be reverted [2] as there were still users left. Libdrm 2.4.33 is now almost 11 years old and it is time for userspace to move on. With the nouveau code gone, we can also remove the driver-feature bit DRIVER_KMS_LEGACY_CONTEXT. Signed-off-by: Thomas Zimmermann Reviewed-by: Karol Herbst Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7c510133d93dd6f15ca040733ba7b2891ed61fd1 # 1 Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c21eb21cb50d58e7cbdcb8b9e7ff68b85cfa5095 # 2 Link: https://patchwork.freedesktop.org/patch/msgid/20230112133858.17087-1-tzimmermann@suse.de --- drivers/gpu/drm/drm_bufs.c | 12 ++++-------- drivers/gpu/drm/drm_context.c | 36 ++++++++++++----------------------- drivers/gpu/drm/nouveau/Kconfig | 12 ------------ drivers/gpu/drm/nouveau/nouveau_drm.c | 10 +++------- include/drm/drm_drv.h | 7 ------- 5 files changed, 19 insertions(+), 58 deletions(-) (limited to 'include') diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index fcca21e8efac..86700560fea2 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -423,8 +423,7 @@ int drm_legacy_addmap_ioctl(struct drm_device *dev, void *data, if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM)) return -EPERM; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; err = drm_addmap_core(dev, map->offset, map->size, map->type, @@ -469,8 +468,7 @@ int drm_legacy_getmap_ioctl(struct drm_device *dev, void *data, int idx; int i; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; idx = map->offset; @@ -570,8 +568,7 @@ EXPORT_SYMBOL(drm_legacy_rmmap_locked); void drm_legacy_rmmap(struct drm_device *dev, struct drm_local_map *map) { - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return; mutex_lock(&dev->struct_mutex); @@ -628,8 +625,7 @@ int drm_legacy_rmmap_ioctl(struct drm_device *dev, void *data, struct drm_map_list *r_list; int ret; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; mutex_lock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/drm_context.c b/drivers/gpu/drm/drm_context.c index c6e6a3e7219a..a0fc779e5e1e 100644 --- a/drivers/gpu/drm/drm_context.c +++ b/drivers/gpu/drm/drm_context.c @@ -59,8 +59,7 @@ struct drm_ctx_list { */ void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle) { - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return; mutex_lock(&dev->struct_mutex); @@ -97,8 +96,7 @@ static int drm_legacy_ctxbitmap_next(struct drm_device * dev) */ void drm_legacy_ctxbitmap_init(struct drm_device * dev) { - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return; idr_init(&dev->ctx_idr); @@ -114,8 +112,7 @@ void drm_legacy_ctxbitmap_init(struct drm_device * dev) */ void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev) { - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return; mutex_lock(&dev->struct_mutex); @@ -136,8 +133,7 @@ void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file) { struct drm_ctx_list *pos, *tmp; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return; mutex_lock(&dev->ctxlist_mutex); @@ -182,8 +178,7 @@ int drm_legacy_getsareactx(struct drm_device *dev, void *data, struct drm_local_map *map; struct drm_map_list *_entry; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; mutex_lock(&dev->struct_mutex); @@ -230,8 +225,7 @@ int drm_legacy_setsareactx(struct drm_device *dev, void *data, struct drm_local_map *map = NULL; struct drm_map_list *r_list = NULL; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; mutex_lock(&dev->struct_mutex); @@ -335,8 +329,7 @@ int drm_legacy_resctx(struct drm_device *dev, void *data, struct drm_ctx ctx; int i; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; if (res->count >= DRM_RESERVED_CONTEXTS) { @@ -370,8 +363,7 @@ int drm_legacy_addctx(struct drm_device *dev, void *data, struct drm_ctx *ctx = data; int tmp_handle; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; tmp_handle = drm_legacy_ctxbitmap_next(dev); @@ -419,8 +411,7 @@ int drm_legacy_getctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; /* This is 0, because we don't handle any context flags */ @@ -445,8 +436,7 @@ int drm_legacy_switchctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; DRM_DEBUG("%d\n", ctx->handle); @@ -469,8 +459,7 @@ int drm_legacy_newctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; DRM_DEBUG("%d\n", ctx->handle); @@ -495,8 +484,7 @@ int drm_legacy_rmctx(struct drm_device *dev, void *data, { struct drm_ctx *ctx = data; - if (!drm_core_check_feature(dev, DRIVER_KMS_LEGACY_CONTEXT) && - !drm_core_check_feature(dev, DRIVER_LEGACY)) + if (!drm_core_check_feature(dev, DRIVER_LEGACY)) return -EOPNOTSUPP; DRM_DEBUG("%d\n", ctx->handle); diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index a0bb3987bf63..a70bd65e1400 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -26,18 +26,6 @@ config DRM_NOUVEAU help Choose this option for open-source NVIDIA support. -config NOUVEAU_LEGACY_CTX_SUPPORT - bool "Nouveau legacy context support" - depends on DRM_NOUVEAU - select DRM_LEGACY - default y - help - There was a version of the nouveau DDX that relied on legacy - ctx ioctls not erroring out. But that was back in time a long - ways, so offer a way to disable it now. For uapi compat with - old nouveau ddx this should be on by default, but modern distros - should consider turning it off. - config NOUVEAU_PLATFORM_DRIVER bool "Nouveau (NVIDIA) SoC GPUs" depends on DRM_NOUVEAU && ARCH_TEGRA diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 80f154b6adab..80562177b581 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1221,13 +1221,9 @@ nouveau_driver_fops = { static struct drm_driver driver_stub = { - .driver_features = - DRIVER_GEM | DRIVER_MODESET | DRIVER_RENDER -#if defined(CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT) - | DRIVER_KMS_LEGACY_CONTEXT -#endif - , - + .driver_features = DRIVER_GEM | + DRIVER_MODESET | + DRIVER_RENDER, .open = nouveau_drm_open, .postclose = nouveau_drm_postclose, .lastclose = nouveau_vga_lastclose, diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 700d3857e088..a3bce427891a 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -141,13 +141,6 @@ enum drm_driver_feature { * Legacy irq support. Only for legacy drivers. Do not use. */ DRIVER_HAVE_IRQ = BIT(30), - /** - * @DRIVER_KMS_LEGACY_CONTEXT: - * - * Used only by nouveau for backwards compatibility with existing - * userspace. Do not use. - */ - DRIVER_KMS_LEGACY_CONTEXT = BIT(31), }; /** -- cgit v1.2.3 From cab18866feade5ffa0cadc5e632528b2050e8e28 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Sat, 3 Dec 2022 18:22:52 +0800 Subject: drm: Remove the obsolete driver-i810 Commit 399516ab0fee ("MAINTAINERS: Add a bunch of legacy (UMS) DRM drivers") marked i810 driver obsolete 7 years ago. And the mesa UMD of this drm driver already in deprecated list in the link: https://docs.mesa3d.org/systems.html Intel i810-->driver/gpu/drm/i810 It's time to remove this driver. Signed-off-by: Cai Huoqing Acked-by: Daniel Vetter Acked-by: Dave Airlie Acked-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20221203102502.3185-2-cai.huoqing@linux.dev --- drivers/gpu/drm/Kconfig | 9 - drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/i810/Makefile | 8 - drivers/gpu/drm/i810/i810_dma.c | 1266 --------------------------------------- drivers/gpu/drm/i810/i810_drv.c | 101 ---- drivers/gpu/drm/i810/i810_drv.h | 246 -------- include/uapi/drm/i810_drm.h | 292 --------- 7 files changed, 1923 deletions(-) delete mode 100644 drivers/gpu/drm/i810/Makefile delete mode 100644 drivers/gpu/drm/i810/i810_dma.c delete mode 100644 drivers/gpu/drm/i810/i810_drv.c delete mode 100644 drivers/gpu/drm/i810/i810_drv.h delete mode 100644 include/uapi/drm/i810_drm.h (limited to 'include') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 748b93d00184..ebcd2d798226 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -414,15 +414,6 @@ config DRM_R128 is selected, the module will be called r128. AGP support for this card is strongly suggested (unless you have a PCI version). -config DRM_I810 - tristate "Intel I810" - # !PREEMPTION because of missing ioctl locking - depends on DRM && AGP && AGP_INTEL && (!PREEMPTION || BROKEN) - help - Choose this option if you have an Intel I810 graphics card. If M is - selected, the module will be called i810. AGP support is required - for this driver to work. - config DRM_MGA tristate "Matrox g200/g400" depends on DRM && PCI diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 8d61fbdfdfac..b20baa165b3b 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -138,7 +138,6 @@ obj-$(CONFIG_DRM_R128) += r128/ obj-$(CONFIG_DRM_RADEON)+= radeon/ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/ obj-$(CONFIG_DRM_MGA) += mga/ -obj-$(CONFIG_DRM_I810) += i810/ obj-$(CONFIG_DRM_I915) += i915/ obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/ obj-$(CONFIG_DRM_MGAG200) += mgag200/ diff --git a/drivers/gpu/drm/i810/Makefile b/drivers/gpu/drm/i810/Makefile deleted file mode 100644 index c181f8528c5c..000000000000 --- a/drivers/gpu/drm/i810/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the drm device driver. This driver provides support for the -# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. - -i810-y := i810_drv.o i810_dma.o - -obj-$(CONFIG_DRM_I810) += i810.o diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c deleted file mode 100644 index 9fb4dd63342f..000000000000 --- a/drivers/gpu/drm/i810/i810_dma.c +++ /dev/null @@ -1,1266 +0,0 @@ -/* i810_dma.c -- DMA support for the i810 -*- linux-c -*- - * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: Rickard E. (Rik) Faith - * Jeff Hartmann - * Keith Whitwell - * - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "i810_drv.h" - -#define I810_BUF_FREE 2 -#define I810_BUF_CLIENT 1 -#define I810_BUF_HARDWARE 0 - -#define I810_BUF_UNMAPPED 0 -#define I810_BUF_MAPPED 1 - -static struct drm_buf *i810_freelist_get(struct drm_device * dev) -{ - struct drm_device_dma *dma = dev->dma; - int i; - int used; - - /* Linear search might not be the best solution */ - - for (i = 0; i < dma->buf_count; i++) { - struct drm_buf *buf = dma->buflist[i]; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - /* In use is already a pointer */ - used = cmpxchg(buf_priv->in_use, I810_BUF_FREE, - I810_BUF_CLIENT); - if (used == I810_BUF_FREE) - return buf; - } - return NULL; -} - -/* This should only be called if the buffer is not sent to the hardware - * yet, the hardware updates in use for us once its on the ring buffer. - */ - -static int i810_freelist_put(struct drm_device *dev, struct drm_buf *buf) -{ - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - int used; - - /* In use is already a pointer */ - used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE); - if (used != I810_BUF_CLIENT) { - DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx); - return -EINVAL; - } - - return 0; -} - -static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev; - drm_i810_private_t *dev_priv; - struct drm_buf *buf; - drm_i810_buf_priv_t *buf_priv; - - dev = priv->minor->dev; - dev_priv = dev->dev_private; - buf = dev_priv->mmap_buffer; - buf_priv = buf->dev_private; - - vma->vm_flags |= VM_DONTCOPY; - - buf_priv->currently_mapped = I810_BUF_MAPPED; - - if (io_remap_pfn_range(vma, vma->vm_start, - vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) - return -EAGAIN; - return 0; -} - -static const struct file_operations i810_buffer_fops = { - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = i810_mmap_buffers, - .compat_ioctl = drm_compat_ioctl, - .llseek = noop_llseek, -}; - -static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv) -{ - struct drm_device *dev = file_priv->minor->dev; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - drm_i810_private_t *dev_priv = dev->dev_private; - const struct file_operations *old_fops; - int retcode = 0; - - if (buf_priv->currently_mapped == I810_BUF_MAPPED) - return -EINVAL; - - /* This is all entirely broken */ - old_fops = file_priv->filp->f_op; - file_priv->filp->f_op = &i810_buffer_fops; - dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)vm_mmap(file_priv->filp, 0, buf->total, - PROT_READ | PROT_WRITE, - MAP_SHARED, buf->bus_address); - dev_priv->mmap_buffer = NULL; - file_priv->filp->f_op = old_fops; - if (IS_ERR(buf_priv->virtual)) { - /* Real error */ - DRM_ERROR("mmap error\n"); - retcode = PTR_ERR(buf_priv->virtual); - buf_priv->virtual = NULL; - } - - return retcode; -} - -static int i810_unmap_buffer(struct drm_buf *buf) -{ - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - int retcode = 0; - - if (buf_priv->currently_mapped != I810_BUF_MAPPED) - return -EINVAL; - - retcode = vm_munmap((unsigned long)buf_priv->virtual, - (size_t) buf->total); - - buf_priv->currently_mapped = I810_BUF_UNMAPPED; - buf_priv->virtual = NULL; - - return retcode; -} - -static int i810_dma_get_buffer(struct drm_device *dev, drm_i810_dma_t *d, - struct drm_file *file_priv) -{ - struct drm_buf *buf; - drm_i810_buf_priv_t *buf_priv; - int retcode = 0; - - buf = i810_freelist_get(dev); - if (!buf) { - retcode = -ENOMEM; - DRM_DEBUG("retcode=%d\n", retcode); - return retcode; - } - - retcode = i810_map_buffer(buf, file_priv); - if (retcode) { - i810_freelist_put(dev, buf); - DRM_ERROR("mapbuf failed, retcode %d\n", retcode); - return retcode; - } - buf->file_priv = file_priv; - buf_priv = buf->dev_private; - d->granted = 1; - d->request_idx = buf->idx; - d->request_size = buf->total; - d->virtual = buf_priv->virtual; - - return retcode; -} - -static int i810_dma_cleanup(struct drm_device *dev) -{ - struct drm_device_dma *dma = dev->dma; - - /* Make sure interrupts are disabled here because the uninstall ioctl - * may not have been called from userspace and after dev_private - * is freed, it's too late. - */ - if (drm_core_check_feature(dev, DRIVER_HAVE_IRQ) && dev->irq_enabled) - drm_legacy_irq_uninstall(dev); - - if (dev->dev_private) { - int i; - drm_i810_private_t *dev_priv = - (drm_i810_private_t *) dev->dev_private; - - if (dev_priv->ring.virtual_start) - drm_legacy_ioremapfree(&dev_priv->ring.map, dev); - if (dev_priv->hw_status_page) { - dma_free_coherent(dev->dev, PAGE_SIZE, - dev_priv->hw_status_page, - dev_priv->dma_status_page); - } - kfree(dev->dev_private); - dev->dev_private = NULL; - - for (i = 0; i < dma->buf_count; i++) { - struct drm_buf *buf = dma->buflist[i]; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - - if (buf_priv->kernel_virtual && buf->total) - drm_legacy_ioremapfree(&buf_priv->map, dev); - } - } - return 0; -} - -static int i810_wait_ring(struct drm_device *dev, int n) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_ring_buffer_t *ring = &(dev_priv->ring); - int iters = 0; - unsigned long end; - unsigned int last_head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; - - end = jiffies + (HZ * 3); - while (ring->space < n) { - ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->Size; - - if (ring->head != last_head) { - end = jiffies + (HZ * 3); - last_head = ring->head; - } - - iters++; - if (time_before(end, jiffies)) { - DRM_ERROR("space: %d wanted %d\n", ring->space, n); - DRM_ERROR("lockup\n"); - goto out_wait_ring; - } - udelay(1); - } - -out_wait_ring: - return iters; -} - -static void i810_kernel_lost_context(struct drm_device *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_ring_buffer_t *ring = &(dev_priv->ring); - - ring->head = I810_READ(LP_RING + RING_HEAD) & HEAD_ADDR; - ring->tail = I810_READ(LP_RING + RING_TAIL); - ring->space = ring->head - (ring->tail + 8); - if (ring->space < 0) - ring->space += ring->Size; -} - -static int i810_freelist_init(struct drm_device *dev, drm_i810_private_t *dev_priv) -{ - struct drm_device_dma *dma = dev->dma; - int my_idx = 24; - u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx); - int i; - - if (dma->buf_count > 1019) { - /* Not enough space in the status page for the freelist */ - return -EINVAL; - } - - for (i = 0; i < dma->buf_count; i++) { - struct drm_buf *buf = dma->buflist[i]; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - - buf_priv->in_use = hw_status++; - buf_priv->my_use_idx = my_idx; - my_idx += 4; - - *buf_priv->in_use = I810_BUF_FREE; - - buf_priv->map.offset = buf->bus_address; - buf_priv->map.size = buf->total; - buf_priv->map.type = _DRM_AGP; - buf_priv->map.flags = 0; - buf_priv->map.mtrr = 0; - - drm_legacy_ioremap(&buf_priv->map, dev); - buf_priv->kernel_virtual = buf_priv->map.handle; - - } - return 0; -} - -static int i810_dma_initialize(struct drm_device *dev, - drm_i810_private_t *dev_priv, - drm_i810_init_t *init) -{ - struct drm_map_list *r_list; - memset(dev_priv, 0, sizeof(drm_i810_private_t)); - - list_for_each_entry(r_list, &dev->maplist, head) { - if (r_list->map && - r_list->map->type == _DRM_SHM && - r_list->map->flags & _DRM_CONTAINS_LOCK) { - dev_priv->sarea_map = r_list->map; - break; - } - } - if (!dev_priv->sarea_map) { - dev->dev_private = (void *)dev_priv; - i810_dma_cleanup(dev); - DRM_ERROR("can not find sarea!\n"); - return -EINVAL; - } - dev_priv->mmio_map = drm_legacy_findmap(dev, init->mmio_offset); - if (!dev_priv->mmio_map) { - dev->dev_private = (void *)dev_priv; - i810_dma_cleanup(dev); - DRM_ERROR("can not find mmio map!\n"); - return -EINVAL; - } - dev->agp_buffer_token = init->buffers_offset; - dev->agp_buffer_map = drm_legacy_findmap(dev, init->buffers_offset); - if (!dev->agp_buffer_map) { - dev->dev_private = (void *)dev_priv; - i810_dma_cleanup(dev); - DRM_ERROR("can not find dma buffer map!\n"); - return -EINVAL; - } - - dev_priv->sarea_priv = (drm_i810_sarea_t *) - ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset); - - dev_priv->ring.Start = init->ring_start; - dev_priv->ring.End = init->ring_end; - dev_priv->ring.Size = init->ring_size; - - dev_priv->ring.map.offset = dev->agp->base + init->ring_start; - dev_priv->ring.map.size = init->ring_size; - dev_priv->ring.map.type = _DRM_AGP; - dev_priv->ring.map.flags = 0; - dev_priv->ring.map.mtrr = 0; - - drm_legacy_ioremap(&dev_priv->ring.map, dev); - - if (dev_priv->ring.map.handle == NULL) { - dev->dev_private = (void *)dev_priv; - i810_dma_cleanup(dev); - DRM_ERROR("can not ioremap virtual address for" - " ring buffer\n"); - return -ENOMEM; - } - - dev_priv->ring.virtual_start = dev_priv->ring.map.handle; - - dev_priv->ring.tail_mask = dev_priv->ring.Size - 1; - - dev_priv->w = init->w; - dev_priv->h = init->h; - dev_priv->pitch = init->pitch; - dev_priv->back_offset = init->back_offset; - dev_priv->depth_offset = init->depth_offset; - dev_priv->front_offset = init->front_offset; - - dev_priv->overlay_offset = init->overlay_offset; - dev_priv->overlay_physical = init->overlay_physical; - - dev_priv->front_di1 = init->front_offset | init->pitch_bits; - dev_priv->back_di1 = init->back_offset | init->pitch_bits; - dev_priv->zi1 = init->depth_offset | init->pitch_bits; - - /* Program Hardware Status Page */ - dev_priv->hw_status_page = - dma_alloc_coherent(dev->dev, PAGE_SIZE, - &dev_priv->dma_status_page, GFP_KERNEL); - if (!dev_priv->hw_status_page) { - dev->dev_private = (void *)dev_priv; - i810_dma_cleanup(dev); - DRM_ERROR("Can not allocate hardware status page\n"); - return -ENOMEM; - } - DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); - - I810_WRITE(0x02080, dev_priv->dma_status_page); - DRM_DEBUG("Enabled hardware status page\n"); - - /* Now we need to init our freelist */ - if (i810_freelist_init(dev, dev_priv) != 0) { - dev->dev_private = (void *)dev_priv; - i810_dma_cleanup(dev); - DRM_ERROR("Not enough space in the status page for" - " the freelist\n"); - return -ENOMEM; - } - dev->dev_private = (void *)dev_priv; - - return 0; -} - -static int i810_dma_init(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i810_private_t *dev_priv; - drm_i810_init_t *init = data; - int retcode = 0; - - switch (init->func) { - case I810_INIT_DMA_1_4: - DRM_INFO("Using v1.4 init.\n"); - dev_priv = kmalloc(sizeof(drm_i810_private_t), GFP_KERNEL); - if (dev_priv == NULL) - return -ENOMEM; - retcode = i810_dma_initialize(dev, dev_priv, init); - break; - - case I810_CLEANUP_DMA: - DRM_INFO("DMA Cleanup\n"); - retcode = i810_dma_cleanup(dev); - break; - default: - return -EINVAL; - } - - return retcode; -} - -/* Most efficient way to verify state for the i810 is as it is - * emitted. Non-conformant state is silently dropped. - * - * Use 'volatile' & local var tmp to force the emitted values to be - * identical to the verified ones. - */ -static void i810EmitContextVerified(struct drm_device *dev, - volatile unsigned int *code) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - int i, j = 0; - unsigned int tmp; - RING_LOCALS; - - BEGIN_LP_RING(I810_CTX_SETUP_SIZE); - - OUT_RING(GFX_OP_COLOR_FACTOR); - OUT_RING(code[I810_CTXREG_CF1]); - - OUT_RING(GFX_OP_STIPPLE); - OUT_RING(code[I810_CTXREG_ST1]); - - for (i = 4; i < I810_CTX_SETUP_SIZE; i++) { - tmp = code[i]; - - if ((tmp & (7 << 29)) == (3 << 29) && - (tmp & (0x1f << 24)) < (0x1d << 24)) { - OUT_RING(tmp); - j++; - } else - printk("constext state dropped!!!\n"); - } - - if (j & 1) - OUT_RING(0); - - ADVANCE_LP_RING(); -} - -static void i810EmitTexVerified(struct drm_device *dev, volatile unsigned int *code) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - int i, j = 0; - unsigned int tmp; - RING_LOCALS; - - BEGIN_LP_RING(I810_TEX_SETUP_SIZE); - - OUT_RING(GFX_OP_MAP_INFO); - OUT_RING(code[I810_TEXREG_MI1]); - OUT_RING(code[I810_TEXREG_MI2]); - OUT_RING(code[I810_TEXREG_MI3]); - - for (i = 4; i < I810_TEX_SETUP_SIZE; i++) { - tmp = code[i]; - - if ((tmp & (7 << 29)) == (3 << 29) && - (tmp & (0x1f << 24)) < (0x1d << 24)) { - OUT_RING(tmp); - j++; - } else - printk("texture state dropped!!!\n"); - } - - if (j & 1) - OUT_RING(0); - - ADVANCE_LP_RING(); -} - -/* Need to do some additional checking when setting the dest buffer. - */ -static void i810EmitDestVerified(struct drm_device *dev, - volatile unsigned int *code) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - unsigned int tmp; - RING_LOCALS; - - BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2); - - tmp = code[I810_DESTREG_DI1]; - if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) { - OUT_RING(CMD_OP_DESTBUFFER_INFO); - OUT_RING(tmp); - } else - DRM_DEBUG("bad di1 %x (allow %x or %x)\n", - tmp, dev_priv->front_di1, dev_priv->back_di1); - - /* invarient: - */ - OUT_RING(CMD_OP_Z_BUFFER_INFO); - OUT_RING(dev_priv->zi1); - - OUT_RING(GFX_OP_DESTBUFFER_VARS); - OUT_RING(code[I810_DESTREG_DV1]); - - OUT_RING(GFX_OP_DRAWRECT_INFO); - OUT_RING(code[I810_DESTREG_DR1]); - OUT_RING(code[I810_DESTREG_DR2]); - OUT_RING(code[I810_DESTREG_DR3]); - OUT_RING(code[I810_DESTREG_DR4]); - OUT_RING(0); - - ADVANCE_LP_RING(); -} - -static void i810EmitState(struct drm_device *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int dirty = sarea_priv->dirty; - - DRM_DEBUG("%x\n", dirty); - - if (dirty & I810_UPLOAD_BUFFERS) { - i810EmitDestVerified(dev, sarea_priv->BufferState); - sarea_priv->dirty &= ~I810_UPLOAD_BUFFERS; - } - - if (dirty & I810_UPLOAD_CTX) { - i810EmitContextVerified(dev, sarea_priv->ContextState); - sarea_priv->dirty &= ~I810_UPLOAD_CTX; - } - - if (dirty & I810_UPLOAD_TEX0) { - i810EmitTexVerified(dev, sarea_priv->TexState[0]); - sarea_priv->dirty &= ~I810_UPLOAD_TEX0; - } - - if (dirty & I810_UPLOAD_TEX1) { - i810EmitTexVerified(dev, sarea_priv->TexState[1]); - sarea_priv->dirty &= ~I810_UPLOAD_TEX1; - } -} - -/* need to verify - */ -static void i810_dma_dispatch_clear(struct drm_device *dev, int flags, - unsigned int clear_color, - unsigned int clear_zval) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; - int nbox = sarea_priv->nbox; - struct drm_clip_rect *pbox = sarea_priv->boxes; - int pitch = dev_priv->pitch; - int cpp = 2; - int i; - RING_LOCALS; - - if (dev_priv->current_page == 1) { - unsigned int tmp = flags; - - flags &= ~(I810_FRONT | I810_BACK); - if (tmp & I810_FRONT) - flags |= I810_BACK; - if (tmp & I810_BACK) - flags |= I810_FRONT; - } - - i810_kernel_lost_context(dev); - - if (nbox > I810_NR_SAREA_CLIPRECTS) - nbox = I810_NR_SAREA_CLIPRECTS; - - for (i = 0; i < nbox; i++, pbox++) { - unsigned int x = pbox->x1; - unsigned int y = pbox->y1; - unsigned int width = (pbox->x2 - x) * cpp; - unsigned int height = pbox->y2 - y; - unsigned int start = y * pitch + x * cpp; - - if (pbox->x1 > pbox->x2 || - pbox->y1 > pbox->y2 || - pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h) - continue; - - if (flags & I810_FRONT) { - BEGIN_LP_RING(6); - OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3); - OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch); - OUT_RING((height << 16) | width); - OUT_RING(start); - OUT_RING(clear_color); - OUT_RING(0); - ADVANCE_LP_RING(); - } - - if (flags & I810_BACK) { - BEGIN_LP_RING(6); - OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3); - OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch); - OUT_RING((height << 16) | width); - OUT_RING(dev_priv->back_offset + start); - OUT_RING(clear_color); - OUT_RING(0); - ADVANCE_LP_RING(); - } - - if (flags & I810_DEPTH) { - BEGIN_LP_RING(6); - OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3); - OUT_RING(BR13_SOLID_PATTERN | (0xF0 << 16) | pitch); - OUT_RING((height << 16) | width); - OUT_RING(dev_priv->depth_offset + start); - OUT_RING(clear_zval); - OUT_RING(0); - ADVANCE_LP_RING(); - } - } -} - -static void i810_dma_dispatch_swap(struct drm_device *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; - int nbox = sarea_priv->nbox; - struct drm_clip_rect *pbox = sarea_priv->boxes; - int pitch = dev_priv->pitch; - int cpp = 2; - int i; - RING_LOCALS; - - DRM_DEBUG("swapbuffers\n"); - - i810_kernel_lost_context(dev); - - if (nbox > I810_NR_SAREA_CLIPRECTS) - nbox = I810_NR_SAREA_CLIPRECTS; - - for (i = 0; i < nbox; i++, pbox++) { - unsigned int w = pbox->x2 - pbox->x1; - unsigned int h = pbox->y2 - pbox->y1; - unsigned int dst = pbox->x1 * cpp + pbox->y1 * pitch; - unsigned int start = dst; - - if (pbox->x1 > pbox->x2 || - pbox->y1 > pbox->y2 || - pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h) - continue; - - BEGIN_LP_RING(6); - OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4); - OUT_RING(pitch | (0xCC << 16)); - OUT_RING((h << 16) | (w * cpp)); - if (dev_priv->current_page == 0) - OUT_RING(dev_priv->front_offset + start); - else - OUT_RING(dev_priv->back_offset + start); - OUT_RING(pitch); - if (dev_priv->current_page == 0) - OUT_RING(dev_priv->back_offset + start); - else - OUT_RING(dev_priv->front_offset + start); - ADVANCE_LP_RING(); - } -} - -static void i810_dma_dispatch_vertex(struct drm_device *dev, - struct drm_buf *buf, int discard, int used) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; - struct drm_clip_rect *box = sarea_priv->boxes; - int nbox = sarea_priv->nbox; - unsigned long address = (unsigned long)buf->bus_address; - unsigned long start = address - dev->agp->base; - int i = 0; - RING_LOCALS; - - i810_kernel_lost_context(dev); - - if (nbox > I810_NR_SAREA_CLIPRECTS) - nbox = I810_NR_SAREA_CLIPRECTS; - - if (used < 0 || used > 4 * 1024) - used = 0; - - if (sarea_priv->dirty) - i810EmitState(dev); - - if (buf_priv->currently_mapped == I810_BUF_MAPPED) { - unsigned int prim = (sarea_priv->vertex_prim & PR_MASK); - - *(u32 *) buf_priv->kernel_virtual = - ((GFX_OP_PRIMITIVE | prim | ((used / 4) - 2))); - - if (used & 4) { - *(u32 *) ((char *) buf_priv->kernel_virtual + used) = 0; - used += 4; - } - - i810_unmap_buffer(buf); - } - - if (used) { - do { - if (i < nbox) { - BEGIN_LP_RING(4); - OUT_RING(GFX_OP_SCISSOR | SC_UPDATE_SCISSOR | - SC_ENABLE); - OUT_RING(GFX_OP_SCISSOR_INFO); - OUT_RING(box[i].x1 | (box[i].y1 << 16)); - OUT_RING((box[i].x2 - - 1) | ((box[i].y2 - 1) << 16)); - ADVANCE_LP_RING(); - } - - BEGIN_LP_RING(4); - OUT_RING(CMD_OP_BATCH_BUFFER); - OUT_RING(start | BB1_PROTECTED); - OUT_RING(start + used - 4); - OUT_RING(0); - ADVANCE_LP_RING(); - - } while (++i < nbox); - } - - if (discard) { - dev_priv->counter++; - - (void)cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, - I810_BUF_HARDWARE); - - BEGIN_LP_RING(8); - OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(20); - OUT_RING(dev_priv->counter); - OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(buf_priv->my_use_idx); - OUT_RING(I810_BUF_FREE); - OUT_RING(CMD_REPORT_HEAD); - OUT_RING(0); - ADVANCE_LP_RING(); - } -} - -static void i810_dma_dispatch_flip(struct drm_device *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - int pitch = dev_priv->pitch; - RING_LOCALS; - - DRM_DEBUG("page=%d pfCurrentPage=%d\n", - dev_priv->current_page, - dev_priv->sarea_priv->pf_current_page); - - i810_kernel_lost_context(dev); - - BEGIN_LP_RING(2); - OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); - OUT_RING(0); - ADVANCE_LP_RING(); - - BEGIN_LP_RING(I810_DEST_SETUP_SIZE + 2); - /* On i815 at least ASYNC is buggy */ - /* pitch<<5 is from 11.2.8 p158, - its the pitch / 8 then left shifted 8, - so (pitch >> 3) << 8 */ - OUT_RING(CMD_OP_FRONTBUFFER_INFO | (pitch << 5) /*| ASYNC_FLIP */ ); - if (dev_priv->current_page == 0) { - OUT_RING(dev_priv->back_offset); - dev_priv->current_page = 1; - } else { - OUT_RING(dev_priv->front_offset); - dev_priv->current_page = 0; - } - OUT_RING(0); - ADVANCE_LP_RING(); - - BEGIN_LP_RING(2); - OUT_RING(CMD_OP_WAIT_FOR_EVENT | WAIT_FOR_PLANE_A_FLIP); - OUT_RING(0); - ADVANCE_LP_RING(); - - /* Increment the frame counter. The client-side 3D driver must - * throttle the framerate by waiting for this value before - * performing the swapbuffer ioctl. - */ - dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; - -} - -static void i810_dma_quiescent(struct drm_device *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - - i810_kernel_lost_context(dev); - - BEGIN_LP_RING(4); - OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); - OUT_RING(CMD_REPORT_HEAD); - OUT_RING(0); - OUT_RING(0); - ADVANCE_LP_RING(); - - i810_wait_ring(dev, dev_priv->ring.Size - 8); -} - -static void i810_flush_queue(struct drm_device *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - int i; - RING_LOCALS; - - i810_kernel_lost_context(dev); - - BEGIN_LP_RING(2); - OUT_RING(CMD_REPORT_HEAD); - OUT_RING(0); - ADVANCE_LP_RING(); - - i810_wait_ring(dev, dev_priv->ring.Size - 8); - - for (i = 0; i < dma->buf_count; i++) { - struct drm_buf *buf = dma->buflist[i]; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - - int used = cmpxchg(buf_priv->in_use, I810_BUF_HARDWARE, - I810_BUF_FREE); - - if (used == I810_BUF_HARDWARE) - DRM_DEBUG("reclaimed from HARDWARE\n"); - if (used == I810_BUF_CLIENT) - DRM_DEBUG("still on client\n"); - } - - return; -} - -/* Must be called with the lock held */ -void i810_driver_reclaim_buffers(struct drm_device *dev, - struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - int i; - - if (!dma) - return; - if (!dev->dev_private) - return; - if (!dma->buflist) - return; - - i810_flush_queue(dev); - - for (i = 0; i < dma->buf_count; i++) { - struct drm_buf *buf = dma->buflist[i]; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - - if (buf->file_priv == file_priv && buf_priv) { - int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, - I810_BUF_FREE); - - if (used == I810_BUF_CLIENT) - DRM_DEBUG("reclaimed from client\n"); - if (buf_priv->currently_mapped == I810_BUF_MAPPED) - buf_priv->currently_mapped = I810_BUF_UNMAPPED; - } - } -} - -static int i810_flush_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - LOCK_TEST_WITH_RETURN(dev, file_priv); - - i810_flush_queue(dev); - return 0; -} - -static int i810_dma_vertex(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - u32 *hw_status = dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - drm_i810_vertex_t *vertex = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DRM_DEBUG("idx %d used %d discard %d\n", - vertex->idx, vertex->used, vertex->discard); - - if (vertex->idx < 0 || vertex->idx >= dma->buf_count) - return -EINVAL; - - i810_dma_dispatch_vertex(dev, - dma->buflist[vertex->idx], - vertex->discard, vertex->used); - - sarea_priv->last_enqueue = dev_priv->counter - 1; - sarea_priv->last_dispatch = (int)hw_status[5]; - - return 0; -} - -static int i810_clear_bufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i810_clear_t *clear = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - /* GH: Someone's doing nasty things... */ - if (!dev->dev_private) - return -EINVAL; - - i810_dma_dispatch_clear(dev, clear->flags, - clear->clear_color, clear->clear_depth); - return 0; -} - -static int i810_swap_bufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - i810_dma_dispatch_swap(dev); - return 0; -} - -static int i810_getage(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - u32 *hw_status = dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - - sarea_priv->last_dispatch = (int)hw_status[5]; - return 0; -} - -static int i810_getbuf(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - int retcode = 0; - drm_i810_dma_t *d = data; - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - u32 *hw_status = dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - d->granted = 0; - - retcode = i810_dma_get_buffer(dev, d, file_priv); - - DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", - task_pid_nr(current), retcode, d->granted); - - sarea_priv->last_dispatch = (int)hw_status[5]; - - return retcode; -} - -static int i810_copybuf(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - /* Never copy - 2.4.x doesn't need it */ - return 0; -} - -static int i810_docopy(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - /* Never copy - 2.4.x doesn't need it */ - return 0; -} - -static void i810_dma_dispatch_mc(struct drm_device *dev, struct drm_buf *buf, int used, - unsigned int last_render) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - drm_i810_buf_priv_t *buf_priv = buf->dev_private; - drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned long address = (unsigned long)buf->bus_address; - unsigned long start = address - dev->agp->base; - int u; - RING_LOCALS; - - i810_kernel_lost_context(dev); - - u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE); - if (u != I810_BUF_CLIENT) - DRM_DEBUG("MC found buffer that isn't mine!\n"); - - if (used < 0 || used > 4 * 1024) - used = 0; - - sarea_priv->dirty = 0x7f; - - DRM_DEBUG("addr 0x%lx, used 0x%x\n", address, used); - - dev_priv->counter++; - DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter); - DRM_DEBUG("start : %lx\n", start); - DRM_DEBUG("used : %d\n", used); - DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4); - - if (buf_priv->currently_mapped == I810_BUF_MAPPED) { - if (used & 4) { - *(u32 *) ((char *) buf_priv->virtual + used) = 0; - used += 4; - } - - i810_unmap_buffer(buf); - } - BEGIN_LP_RING(4); - OUT_RING(CMD_OP_BATCH_BUFFER); - OUT_RING(start | BB1_PROTECTED); - OUT_RING(start + used - 4); - OUT_RING(0); - ADVANCE_LP_RING(); - - BEGIN_LP_RING(8); - OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(buf_priv->my_use_idx); - OUT_RING(I810_BUF_FREE); - OUT_RING(0); - - OUT_RING(CMD_STORE_DWORD_IDX); - OUT_RING(16); - OUT_RING(last_render); - OUT_RING(0); - ADVANCE_LP_RING(); -} - -static int i810_dma_mc(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - u32 *hw_status = dev_priv->hw_status_page; - drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) - dev_priv->sarea_priv; - drm_i810_mc_t *mc = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (mc->idx >= dma->buf_count || mc->idx < 0) - return -EINVAL; - - i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used, - mc->last_render); - - sarea_priv->last_enqueue = dev_priv->counter - 1; - sarea_priv->last_dispatch = (int)hw_status[5]; - - return 0; -} - -static int i810_rstatus(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - - return (int)(((u32 *) (dev_priv->hw_status_page))[4]); -} - -static int i810_ov0_info(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - drm_i810_overlay_t *ov = data; - - ov->offset = dev_priv->overlay_offset; - ov->physical = dev_priv->overlay_physical; - - return 0; -} - -static int i810_fstatus(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - return I810_READ(0x30008); -} - -static int i810_ov0_flip(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - /* Tell the overlay to update */ - I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000); - - return 0; -} - -/* Not sure why this isn't set all the time: - */ -static void i810_do_init_pageflip(struct drm_device *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - - DRM_DEBUG("\n"); - dev_priv->page_flipping = 1; - dev_priv->current_page = 0; - dev_priv->sarea_priv->pf_current_page = dev_priv->current_page; -} - -static int i810_do_cleanup_pageflip(struct drm_device *dev) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - - DRM_DEBUG("\n"); - if (dev_priv->current_page != 0) - i810_dma_dispatch_flip(dev); - - dev_priv->page_flipping = 0; - return 0; -} - -static int i810_flip_bufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i810_private_t *dev_priv = dev->dev_private; - - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (!dev_priv->page_flipping) - i810_do_init_pageflip(dev); - - i810_dma_dispatch_flip(dev); - return 0; -} - -int i810_driver_load(struct drm_device *dev, unsigned long flags) -{ - struct pci_dev *pdev = to_pci_dev(dev->dev); - - dev->agp = drm_legacy_agp_init(dev); - if (dev->agp) { - dev->agp->agp_mtrr = arch_phys_wc_add( - dev->agp->agp_info.aper_base, - dev->agp->agp_info.aper_size * - 1024 * 1024); - } - - /* Our userspace depends upon the agp mapping support. */ - if (!dev->agp) - return -EINVAL; - - pci_set_master(pdev); - - return 0; -} - -void i810_driver_lastclose(struct drm_device *dev) -{ - i810_dma_cleanup(dev); -} - -void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) -{ - if (dev->dev_private) { - drm_i810_private_t *dev_priv = dev->dev_private; - if (dev_priv->page_flipping) - i810_do_cleanup_pageflip(dev); - } - - if (file_priv->master && file_priv->master->lock.hw_lock) { - drm_legacy_idlelock_take(&file_priv->master->lock); - i810_driver_reclaim_buffers(dev, file_priv); - drm_legacy_idlelock_release(&file_priv->master->lock); - } else { - /* master disappeared, clean up stuff anyway and hope nothing - * goes wrong */ - i810_driver_reclaim_buffers(dev, file_priv); - } - -} - -int i810_driver_dma_quiescent(struct drm_device *dev) -{ - i810_dma_quiescent(dev); - return 0; -} - -const struct drm_ioctl_desc i810_ioctls[] = { - DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF_DRV(I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED), -}; - -int i810_max_ioctl = ARRAY_SIZE(i810_ioctls); diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c deleted file mode 100644 index 0e53a066d4db..000000000000 --- a/drivers/gpu/drm/i810/i810_drv.c +++ /dev/null @@ -1,101 +0,0 @@ -/* i810_drv.c -- I810 driver -*- linux-c -*- - * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Rickard E. (Rik) Faith - * Jeff Hartmann - * Gareth Hughes - */ - -#include "i810_drv.h" - -#include -#include - -#include -#include -#include -#include - - -static struct pci_device_id pciidlist[] = { - i810_PCI_IDS -}; - -static const struct file_operations i810_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = drm_legacy_mmap, - .poll = drm_poll, - .compat_ioctl = drm_compat_ioctl, - .llseek = noop_llseek, -}; - -static struct drm_driver driver = { - .driver_features = DRIVER_USE_AGP | DRIVER_HAVE_DMA | DRIVER_LEGACY, - .dev_priv_size = sizeof(drm_i810_buf_priv_t), - .load = i810_driver_load, - .lastclose = i810_driver_lastclose, - .preclose = i810_driver_preclose, - .dma_quiescent = i810_driver_dma_quiescent, - .ioctls = i810_ioctls, - .fops = &i810_driver_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; - -static struct pci_driver i810_pci_driver = { - .name = DRIVER_NAME, - .id_table = pciidlist, -}; - -static int __init i810_init(void) -{ - if (num_possible_cpus() > 1) { - pr_err("drm/i810 does not support SMP\n"); - return -EINVAL; - } - driver.num_ioctls = i810_max_ioctl; - return drm_legacy_pci_init(&driver, &i810_pci_driver); -} - -static void __exit i810_exit(void) -{ - drm_legacy_pci_exit(&driver, &i810_pci_driver); -} - -module_init(i810_init); -module_exit(i810_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h deleted file mode 100644 index 9df3981ffc66..000000000000 --- a/drivers/gpu/drm/i810/i810_drv.h +++ /dev/null @@ -1,246 +0,0 @@ -/* i810_drv.h -- Private header for the Matrox g200/g400 driver -*- linux-c -*- - * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: Rickard E. (Rik) Faith - * Jeff Hartmann - * - */ - -#ifndef _I810_DRV_H_ -#define _I810_DRV_H_ - -#include -#include -#include - -/* General customization: - */ - -#define DRIVER_AUTHOR "VA Linux Systems Inc." - -#define DRIVER_NAME "i810" -#define DRIVER_DESC "Intel i810" -#define DRIVER_DATE "20030605" - -/* Interface history - * - * 1.1 - XFree86 4.1 - * 1.2 - XvMC interfaces - * - XFree86 4.2 - * 1.2.1 - Disable copying code (leave stub ioctls for backwards compatibility) - * - Remove requirement for interrupt (leave stubs again) - * 1.3 - Add page flipping. - * 1.4 - fix DRM interface - */ -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 4 -#define DRIVER_PATCHLEVEL 0 - -typedef struct drm_i810_buf_priv { - u32 *in_use; - int my_use_idx; - int currently_mapped; - void *virtual; - void *kernel_virtual; - drm_local_map_t map; -} drm_i810_buf_priv_t; - -typedef struct _drm_i810_ring_buffer { - int tail_mask; - unsigned long Start; - unsigned long End; - unsigned long Size; - u8 *virtual_start; - int head; - int tail; - int space; - drm_local_map_t map; -} drm_i810_ring_buffer_t; - -typedef struct drm_i810_private { - struct drm_local_map *sarea_map; - struct drm_local_map *mmio_map; - - drm_i810_sarea_t *sarea_priv; - drm_i810_ring_buffer_t ring; - - void *hw_status_page; - unsigned long counter; - - dma_addr_t dma_status_page; - - struct drm_buf *mmap_buffer; - - u32 front_di1, back_di1, zi1; - - int back_offset; - int depth_offset; - int overlay_offset; - int overlay_physical; - int w, h; - int pitch; - int back_pitch; - int depth_pitch; - - int do_boxes; - int dma_used; - - int current_page; - int page_flipping; - - wait_queue_head_t irq_queue; - atomic_t irq_received; - atomic_t irq_emitted; - - int front_offset; -} drm_i810_private_t; - - /* i810_dma.c */ -extern int i810_driver_dma_quiescent(struct drm_device *dev); -void i810_driver_reclaim_buffers(struct drm_device *dev, - struct drm_file *file_priv); -extern int i810_driver_load(struct drm_device *, unsigned long flags); -extern void i810_driver_lastclose(struct drm_device *dev); -extern void i810_driver_preclose(struct drm_device *dev, - struct drm_file *file_priv); - -extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -extern const struct drm_ioctl_desc i810_ioctls[]; -extern int i810_max_ioctl; - -#define I810_BASE(reg) ((unsigned long) \ - dev_priv->mmio_map->handle) -#define I810_ADDR(reg) (I810_BASE(reg) + reg) -#define I810_DEREF(reg) (*(__volatile__ int *)I810_ADDR(reg)) -#define I810_READ(reg) I810_DEREF(reg) -#define I810_WRITE(reg, val) do { I810_DEREF(reg) = val; } while (0) -#define I810_DEREF16(reg) (*(__volatile__ u16 *)I810_ADDR(reg)) -#define I810_READ16(reg) I810_DEREF16(reg) -#define I810_WRITE16(reg, val) do { I810_DEREF16(reg) = val; } while (0) - -#define I810_VERBOSE 0 -#define RING_LOCALS unsigned int outring, ringmask; \ - volatile char *virt; - -#define BEGIN_LP_RING(n) do { \ - if (I810_VERBOSE) \ - DRM_DEBUG("BEGIN_LP_RING(%d)\n", n); \ - if (dev_priv->ring.space < n*4) \ - i810_wait_ring(dev, n*4); \ - dev_priv->ring.space -= n*4; \ - outring = dev_priv->ring.tail; \ - ringmask = dev_priv->ring.tail_mask; \ - virt = dev_priv->ring.virtual_start; \ -} while (0) - -#define ADVANCE_LP_RING() do { \ - if (I810_VERBOSE) \ - DRM_DEBUG("ADVANCE_LP_RING\n"); \ - dev_priv->ring.tail = outring; \ - I810_WRITE(LP_RING + RING_TAIL, outring); \ -} while (0) - -#define OUT_RING(n) do { \ - if (I810_VERBOSE) \ - DRM_DEBUG(" OUT_RING %x\n", (int)(n)); \ - *(volatile unsigned int *)(virt + outring) = n; \ - outring += 4; \ - outring &= ringmask; \ -} while (0) - -#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) -#define GFX_OP_BREAKPOINT_INTERRUPT ((0<<29)|(1<<23)) -#define CMD_REPORT_HEAD (7<<23) -#define CMD_STORE_DWORD_IDX ((0x21<<23) | 0x1) -#define CMD_OP_BATCH_BUFFER ((0x0<<29)|(0x30<<23)|0x1) - -#define INST_PARSER_CLIENT 0x00000000 -#define INST_OP_FLUSH 0x02000000 -#define INST_FLUSH_MAP_CACHE 0x00000001 - -#define BB1_START_ADDR_MASK (~0x7) -#define BB1_PROTECTED (1<<0) -#define BB1_UNPROTECTED (0<<0) -#define BB2_END_ADDR_MASK (~0x7) - -#define I810REG_HWSTAM 0x02098 -#define I810REG_INT_IDENTITY_R 0x020a4 -#define I810REG_INT_MASK_R 0x020a8 -#define I810REG_INT_ENABLE_R 0x020a0 - -#define LP_RING 0x2030 -#define HP_RING 0x2040 -#define RING_TAIL 0x00 -#define TAIL_ADDR 0x000FFFF8 -#define RING_HEAD 0x04 -#define HEAD_WRAP_COUNT 0xFFE00000 -#define HEAD_WRAP_ONE 0x00200000 -#define HEAD_ADDR 0x001FFFFC -#define RING_START 0x08 -#define START_ADDR 0x00FFFFF8 -#define RING_LEN 0x0C -#define RING_NR_PAGES 0x000FF000 -#define RING_REPORT_MASK 0x00000006 -#define RING_REPORT_64K 0x00000002 -#define RING_REPORT_128K 0x00000004 -#define RING_NO_REPORT 0x00000000 -#define RING_VALID_MASK 0x00000001 -#define RING_VALID 0x00000001 -#define RING_INVALID 0x00000000 - -#define GFX_OP_SCISSOR ((0x3<<29)|(0x1c<<24)|(0x10<<19)) -#define SC_UPDATE_SCISSOR (0x1<<1) -#define SC_ENABLE_MASK (0x1<<0) -#define SC_ENABLE (0x1<<0) - -#define GFX_OP_SCISSOR_INFO ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1)) -#define SCI_YMIN_MASK (0xffff<<16) -#define SCI_XMIN_MASK (0xffff<<0) -#define SCI_YMAX_MASK (0xffff<<16) -#define SCI_XMAX_MASK (0xffff<<0) - -#define GFX_OP_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0) -#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) -#define GFX_OP_MAP_INFO ((0x3<<29)|(0x1d<<24)|0x2) -#define GFX_OP_DESTBUFFER_VARS ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0) -#define GFX_OP_DRAWRECT_INFO ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3)) -#define GFX_OP_PRIMITIVE ((0x3<<29)|(0x1f<<24)) - -#define CMD_OP_Z_BUFFER_INFO ((0x0<<29)|(0x16<<23)) -#define CMD_OP_DESTBUFFER_INFO ((0x0<<29)|(0x15<<23)) -#define CMD_OP_FRONTBUFFER_INFO ((0x0<<29)|(0x14<<23)) -#define CMD_OP_WAIT_FOR_EVENT ((0x0<<29)|(0x03<<23)) - -#define BR00_BITBLT_CLIENT 0x40000000 -#define BR00_OP_COLOR_BLT 0x10000000 -#define BR00_OP_SRC_COPY_BLT 0x10C00000 -#define BR13_SOLID_PATTERN 0x80000000 - -#define WAIT_FOR_PLANE_A_SCANLINES (1<<1) -#define WAIT_FOR_PLANE_A_FLIP (1<<2) -#define WAIT_FOR_VBLANK (1<<3) - -#endif diff --git a/include/uapi/drm/i810_drm.h b/include/uapi/drm/i810_drm.h deleted file mode 100644 index d285d5e72e6a..000000000000 --- a/include/uapi/drm/i810_drm.h +++ /dev/null @@ -1,292 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _I810_DRM_H_ -#define _I810_DRM_H_ - -#include "drm.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -/* WARNING: These defines must be the same as what the Xserver uses. - * if you change them, you must change the defines in the Xserver. - */ - -#ifndef _I810_DEFINES_ -#define _I810_DEFINES_ - -#define I810_DMA_BUF_ORDER 12 -#define I810_DMA_BUF_SZ (1< Date: Sat, 3 Dec 2022 18:22:53 +0800 Subject: drm: Remove the obsolete driver-mga Commit 399516ab0fee ("MAINTAINERS: Add a bunch of legacy (UMS) DRM drivers") marked mga driver obsolete 7 years ago. And the mesa UMD of this drm driver already in deprecated list in the link: https://docs.mesa3d.org/systems.html Matrox-->driver/gpu/drm/mga It's time to remove this driver. Signed-off-by: Cai Huoqing Acked-by: Daniel Vetter Acked-by: Dave Airlie Acked-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20221203102502.3185-3-cai.huoqing@linux.dev --- drivers/gpu/drm/Kconfig | 9 - drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/mga/Makefile | 11 - drivers/gpu/drm/mga/mga_dma.c | 1168 --------------------------------------- drivers/gpu/drm/mga/mga_drv.c | 104 ---- drivers/gpu/drm/mga/mga_drv.h | 685 ----------------------- drivers/gpu/drm/mga/mga_ioc32.c | 197 ------- drivers/gpu/drm/mga/mga_irq.c | 169 ------ drivers/gpu/drm/mga/mga_state.c | 1099 ------------------------------------ drivers/gpu/drm/mga/mga_warp.c | 167 ------ include/uapi/drm/mga_drm.h | 429 -------------- 11 files changed, 4039 deletions(-) delete mode 100644 drivers/gpu/drm/mga/Makefile delete mode 100644 drivers/gpu/drm/mga/mga_dma.c delete mode 100644 drivers/gpu/drm/mga/mga_drv.c delete mode 100644 drivers/gpu/drm/mga/mga_drv.h delete mode 100644 drivers/gpu/drm/mga/mga_ioc32.c delete mode 100644 drivers/gpu/drm/mga/mga_irq.c delete mode 100644 drivers/gpu/drm/mga/mga_state.c delete mode 100644 drivers/gpu/drm/mga/mga_warp.c delete mode 100644 include/uapi/drm/mga_drm.h (limited to 'include') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index ebcd2d798226..3aba47a790c3 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -414,15 +414,6 @@ config DRM_R128 is selected, the module will be called r128. AGP support for this card is strongly suggested (unless you have a PCI version). -config DRM_MGA - tristate "Matrox g200/g400" - depends on DRM && PCI - select FW_LOADER - help - Choose this option if you have a Matrox G200, G400 or G450 graphics - card. If M is selected, the module will be called mga. AGP - support is required for this driver to work. - config DRM_SIS tristate "SiS video cards" depends on DRM && AGP diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index b20baa165b3b..306f1f8fd830 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -137,7 +137,6 @@ obj-$(CONFIG_DRM_TDFX) += tdfx/ obj-$(CONFIG_DRM_R128) += r128/ obj-$(CONFIG_DRM_RADEON)+= radeon/ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/ -obj-$(CONFIG_DRM_MGA) += mga/ obj-$(CONFIG_DRM_I915) += i915/ obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/ obj-$(CONFIG_DRM_MGAG200) += mgag200/ diff --git a/drivers/gpu/drm/mga/Makefile b/drivers/gpu/drm/mga/Makefile deleted file mode 100644 index db07c7fcc996..000000000000 --- a/drivers/gpu/drm/mga/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the drm device driver. This driver provides support for the -# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. - -mga-y := mga_drv.o mga_dma.o mga_state.o mga_warp.o mga_irq.o - -mga-$(CONFIG_COMPAT) += mga_ioc32.o - -obj-$(CONFIG_DRM_MGA) += mga.o - diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c deleted file mode 100644 index 331c2f0da57a..000000000000 --- a/drivers/gpu/drm/mga/mga_dma.c +++ /dev/null @@ -1,1168 +0,0 @@ -/* mga_dma.c -- DMA support for mga g200/g400 -*- linux-c -*- - * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* - * \file mga_dma.c - * DMA support for MGA G200 / G400. - * - * \author Rickard E. (Rik) Faith - * \author Jeff Hartmann - * \author Keith Whitwell - * \author Gareth Hughes - */ - -#include - -#include "mga_drv.h" - -#define MGA_DEFAULT_USEC_TIMEOUT 10000 -#define MGA_FREELIST_DEBUG 0 - -#define MINIMAL_CLEANUP 0 -#define FULL_CLEANUP 1 -static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup); - -/* ================================================================ - * Engine control - */ - -int mga_do_wait_for_idle(drm_mga_private_t *dev_priv) -{ - u32 status = 0; - int i; - DRM_DEBUG("\n"); - - for (i = 0; i < dev_priv->usec_timeout; i++) { - status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; - if (status == MGA_ENDPRDMASTS) { - MGA_WRITE8(MGA_CRTC_INDEX, 0); - return 0; - } - udelay(1); - } - -#if MGA_DMA_DEBUG - DRM_ERROR("failed!\n"); - DRM_INFO(" status=0x%08x\n", status); -#endif - return -EBUSY; -} - -static int mga_do_dma_reset(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_primary_buffer_t *primary = &dev_priv->prim; - - DRM_DEBUG("\n"); - - /* The primary DMA stream should look like new right about now. - */ - primary->tail = 0; - primary->space = primary->size; - primary->last_flush = 0; - - sarea_priv->last_wrap = 0; - - /* FIXME: Reset counters, buffer ages etc... - */ - - /* FIXME: What else do we need to reinitialize? WARP stuff? - */ - - return 0; -} - -/* ================================================================ - * Primary DMA stream - */ - -void mga_do_dma_flush(drm_mga_private_t *dev_priv) -{ - drm_mga_primary_buffer_t *primary = &dev_priv->prim; - u32 head, tail; - u32 status = 0; - int i; - DMA_LOCALS; - DRM_DEBUG("\n"); - - /* We need to wait so that we can do an safe flush */ - for (i = 0; i < dev_priv->usec_timeout; i++) { - status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; - if (status == MGA_ENDPRDMASTS) - break; - udelay(1); - } - - if (primary->tail == primary->last_flush) { - DRM_DEBUG(" bailing out...\n"); - return; - } - - tail = primary->tail + dev_priv->primary->offset; - - /* We need to pad the stream between flushes, as the card - * actually (partially?) reads the first of these commands. - * See page 4-16 in the G400 manual, middle of the page or so. - */ - BEGIN_DMA(1); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); - - ADVANCE_DMA(); - - primary->last_flush = primary->tail; - - head = MGA_READ(MGA_PRIMADDRESS); - - if (head <= tail) - primary->space = primary->size - primary->tail; - else - primary->space = head - tail; - - DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset)); - DRM_DEBUG(" tail = 0x%06lx\n", (unsigned long)(tail - dev_priv->primary->offset)); - DRM_DEBUG(" space = 0x%06x\n", primary->space); - - mga_flush_write_combine(); - MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access); - - DRM_DEBUG("done.\n"); -} - -void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv) -{ - drm_mga_primary_buffer_t *primary = &dev_priv->prim; - u32 head, tail; - DMA_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_DMA_WRAP(); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); - - ADVANCE_DMA(); - - tail = primary->tail + dev_priv->primary->offset; - - primary->tail = 0; - primary->last_flush = 0; - primary->last_wrap++; - - head = MGA_READ(MGA_PRIMADDRESS); - - if (head == dev_priv->primary->offset) - primary->space = primary->size; - else - primary->space = head - dev_priv->primary->offset; - - DRM_DEBUG(" head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset)); - DRM_DEBUG(" tail = 0x%06x\n", primary->tail); - DRM_DEBUG(" wrap = %d\n", primary->last_wrap); - DRM_DEBUG(" space = 0x%06x\n", primary->space); - - mga_flush_write_combine(); - MGA_WRITE(MGA_PRIMEND, tail | dev_priv->dma_access); - - set_bit(0, &primary->wrapped); - DRM_DEBUG("done.\n"); -} - -void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv) -{ - drm_mga_primary_buffer_t *primary = &dev_priv->prim; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - u32 head = dev_priv->primary->offset; - DRM_DEBUG("\n"); - - sarea_priv->last_wrap++; - DRM_DEBUG(" wrap = %d\n", sarea_priv->last_wrap); - - mga_flush_write_combine(); - MGA_WRITE(MGA_PRIMADDRESS, head | MGA_DMA_GENERAL); - - clear_bit(0, &primary->wrapped); - DRM_DEBUG("done.\n"); -} - -/* ================================================================ - * Freelist management - */ - -#define MGA_BUFFER_USED (~0) -#define MGA_BUFFER_FREE 0 - -#if MGA_FREELIST_DEBUG -static void mga_freelist_print(struct drm_device *dev) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_freelist_t *entry; - - DRM_INFO("\n"); - DRM_INFO("current dispatch: last=0x%x done=0x%x\n", - dev_priv->sarea_priv->last_dispatch, - (unsigned int)(MGA_READ(MGA_PRIMADDRESS) - - dev_priv->primary->offset)); - DRM_INFO("current freelist:\n"); - - for (entry = dev_priv->head->next; entry; entry = entry->next) { - DRM_INFO(" %p idx=%2d age=0x%x 0x%06lx\n", - entry, entry->buf->idx, entry->age.head, - (unsigned long)(entry->age.head - dev_priv->primary->offset)); - } - DRM_INFO("\n"); -} -#endif - -static int mga_freelist_init(struct drm_device *dev, drm_mga_private_t *dev_priv) -{ - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_mga_buf_priv_t *buf_priv; - drm_mga_freelist_t *entry; - int i; - DRM_DEBUG("count=%d\n", dma->buf_count); - - dev_priv->head = kzalloc(sizeof(drm_mga_freelist_t), GFP_KERNEL); - if (dev_priv->head == NULL) - return -ENOMEM; - - SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0); - - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - - entry = kzalloc(sizeof(drm_mga_freelist_t), GFP_KERNEL); - if (entry == NULL) - return -ENOMEM; - - entry->next = dev_priv->head->next; - entry->prev = dev_priv->head; - SET_AGE(&entry->age, MGA_BUFFER_FREE, 0); - entry->buf = buf; - - if (dev_priv->head->next != NULL) - dev_priv->head->next->prev = entry; - if (entry->next == NULL) - dev_priv->tail = entry; - - buf_priv->list_entry = entry; - buf_priv->discard = 0; - buf_priv->dispatched = 0; - - dev_priv->head->next = entry; - } - - return 0; -} - -static void mga_freelist_cleanup(struct drm_device *dev) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_freelist_t *entry; - drm_mga_freelist_t *next; - DRM_DEBUG("\n"); - - entry = dev_priv->head; - while (entry) { - next = entry->next; - kfree(entry); - entry = next; - } - - dev_priv->head = dev_priv->tail = NULL; -} - -#if 0 -/* FIXME: Still needed? - */ -static void mga_freelist_reset(struct drm_device *dev) -{ - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_mga_buf_priv_t *buf_priv; - int i; - - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - SET_AGE(&buf_priv->list_entry->age, MGA_BUFFER_FREE, 0); - } -} -#endif - -static struct drm_buf *mga_freelist_get(struct drm_device * dev) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_freelist_t *next; - drm_mga_freelist_t *prev; - drm_mga_freelist_t *tail = dev_priv->tail; - u32 head, wrap; - DRM_DEBUG("\n"); - - head = MGA_READ(MGA_PRIMADDRESS); - wrap = dev_priv->sarea_priv->last_wrap; - - DRM_DEBUG(" tail=0x%06lx %d\n", - tail->age.head ? - (unsigned long)(tail->age.head - dev_priv->primary->offset) : 0, - tail->age.wrap); - DRM_DEBUG(" head=0x%06lx %d\n", - (unsigned long)(head - dev_priv->primary->offset), wrap); - - if (TEST_AGE(&tail->age, head, wrap)) { - prev = dev_priv->tail->prev; - next = dev_priv->tail; - prev->next = NULL; - next->prev = next->next = NULL; - dev_priv->tail = prev; - SET_AGE(&next->age, MGA_BUFFER_USED, 0); - return next->buf; - } - - DRM_DEBUG("returning NULL!\n"); - return NULL; -} - -int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_buf_priv_t *buf_priv = buf->dev_private; - drm_mga_freelist_t *head, *entry, *prev; - - DRM_DEBUG("age=0x%06lx wrap=%d\n", - (unsigned long)(buf_priv->list_entry->age.head - - dev_priv->primary->offset), - buf_priv->list_entry->age.wrap); - - entry = buf_priv->list_entry; - head = dev_priv->head; - - if (buf_priv->list_entry->age.head == MGA_BUFFER_USED) { - SET_AGE(&entry->age, MGA_BUFFER_FREE, 0); - prev = dev_priv->tail; - prev->next = entry; - entry->prev = prev; - entry->next = NULL; - } else { - prev = head->next; - head->next = entry; - prev->prev = entry; - entry->prev = head; - entry->next = prev; - } - - return 0; -} - -/* ================================================================ - * DMA initialization, cleanup - */ - -int mga_driver_load(struct drm_device *dev, unsigned long flags) -{ - struct pci_dev *pdev = to_pci_dev(dev->dev); - drm_mga_private_t *dev_priv; - int ret; - - /* There are PCI versions of the G450. These cards have the - * same PCI ID as the AGP G450, but have an additional PCI-to-PCI - * bridge chip. We detect these cards, which are not currently - * supported by this driver, by looking at the device ID of the - * bus the "card" is on. If vendor is 0x3388 (Hint Corp) and the - * device is 0x0021 (HB6 Universal PCI-PCI bridge), we reject the - * device. - */ - if ((pdev->device == 0x0525) && pdev->bus->self - && (pdev->bus->self->vendor == 0x3388) - && (pdev->bus->self->device == 0x0021) - && dev->agp) { - /* FIXME: This should be quirked in the pci core, but oh well - * the hw probably stopped existing. */ - arch_phys_wc_del(dev->agp->agp_mtrr); - kfree(dev->agp); - dev->agp = NULL; - } - dev_priv = kzalloc(sizeof(drm_mga_private_t), GFP_KERNEL); - if (!dev_priv) - return -ENOMEM; - - dev->dev_private = (void *)dev_priv; - - dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT; - dev_priv->chipset = flags; - - pci_set_master(pdev); - - dev_priv->mmio_base = pci_resource_start(pdev, 1); - dev_priv->mmio_size = pci_resource_len(pdev, 1); - - ret = drm_vblank_init(dev, 1); - - if (ret) { - (void) mga_driver_unload(dev); - return ret; - } - - return 0; -} - -#if IS_ENABLED(CONFIG_AGP) -/* - * Bootstrap the driver for AGP DMA. - * - * \todo - * Investigate whether there is any benefit to storing the WARP microcode in - * AGP memory. If not, the microcode may as well always be put in PCI - * memory. - * - * \todo - * This routine needs to set dma_bs->agp_mode to the mode actually configured - * in the hardware. Looking just at the Linux AGP driver code, I don't see - * an easy way to determine this. - * - * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap - */ -static int mga_do_agp_dma_bootstrap(struct drm_device *dev, - drm_mga_dma_bootstrap_t *dma_bs) -{ - drm_mga_private_t *const dev_priv = - (drm_mga_private_t *) dev->dev_private; - unsigned int warp_size = MGA_WARP_UCODE_SIZE; - int err; - unsigned offset; - const unsigned secondary_size = dma_bs->secondary_bin_count - * dma_bs->secondary_bin_size; - const unsigned agp_size = (dma_bs->agp_size << 20); - struct drm_buf_desc req; - struct drm_agp_mode mode; - struct drm_agp_info info; - struct drm_agp_buffer agp_req; - struct drm_agp_binding bind_req; - - /* Acquire AGP. */ - err = drm_legacy_agp_acquire(dev); - if (err) { - DRM_ERROR("Unable to acquire AGP: %d\n", err); - return err; - } - - err = drm_legacy_agp_info(dev, &info); - if (err) { - DRM_ERROR("Unable to get AGP info: %d\n", err); - return err; - } - - mode.mode = (info.mode & ~0x07) | dma_bs->agp_mode; - err = drm_legacy_agp_enable(dev, mode); - if (err) { - DRM_ERROR("Unable to enable AGP (mode = 0x%lx)\n", mode.mode); - return err; - } - - /* In addition to the usual AGP mode configuration, the G200 AGP cards - * need to have the AGP mode "manually" set. - */ - - if (dev_priv->chipset == MGA_CARD_TYPE_G200) { - if (mode.mode & 0x02) - MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE); - else - MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE); - } - - /* Allocate and bind AGP memory. */ - agp_req.size = agp_size; - agp_req.type = 0; - err = drm_legacy_agp_alloc(dev, &agp_req); - if (err) { - dev_priv->agp_size = 0; - DRM_ERROR("Unable to allocate %uMB AGP memory\n", - dma_bs->agp_size); - return err; - } - - dev_priv->agp_size = agp_size; - dev_priv->agp_handle = agp_req.handle; - - bind_req.handle = agp_req.handle; - bind_req.offset = 0; - err = drm_legacy_agp_bind(dev, &bind_req); - if (err) { - DRM_ERROR("Unable to bind AGP memory: %d\n", err); - return err; - } - - /* Make drm_legacy_addbufs happy by not trying to create a mapping for - * less than a page. - */ - if (warp_size < PAGE_SIZE) - warp_size = PAGE_SIZE; - - offset = 0; - err = drm_legacy_addmap(dev, offset, warp_size, - _DRM_AGP, _DRM_READ_ONLY, &dev_priv->warp); - if (err) { - DRM_ERROR("Unable to map WARP microcode: %d\n", err); - return err; - } - - offset += warp_size; - err = drm_legacy_addmap(dev, offset, dma_bs->primary_size, - _DRM_AGP, _DRM_READ_ONLY, &dev_priv->primary); - if (err) { - DRM_ERROR("Unable to map primary DMA region: %d\n", err); - return err; - } - - offset += dma_bs->primary_size; - err = drm_legacy_addmap(dev, offset, secondary_size, - _DRM_AGP, 0, &dev->agp_buffer_map); - if (err) { - DRM_ERROR("Unable to map secondary DMA region: %d\n", err); - return err; - } - - (void)memset(&req, 0, sizeof(req)); - req.count = dma_bs->secondary_bin_count; - req.size = dma_bs->secondary_bin_size; - req.flags = _DRM_AGP_BUFFER; - req.agp_start = offset; - - err = drm_legacy_addbufs_agp(dev, &req); - if (err) { - DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); - return err; - } - - { - struct drm_map_list *_entry; - unsigned long agp_token = 0; - - list_for_each_entry(_entry, &dev->maplist, head) { - if (_entry->map == dev->agp_buffer_map) - agp_token = _entry->user_token; - } - if (!agp_token) - return -EFAULT; - - dev->agp_buffer_token = agp_token; - } - - offset += secondary_size; - err = drm_legacy_addmap(dev, offset, agp_size - offset, - _DRM_AGP, 0, &dev_priv->agp_textures); - if (err) { - DRM_ERROR("Unable to map AGP texture region %d\n", err); - return err; - } - - drm_legacy_ioremap(dev_priv->warp, dev); - drm_legacy_ioremap(dev_priv->primary, dev); - drm_legacy_ioremap(dev->agp_buffer_map, dev); - - if (!dev_priv->warp->handle || - !dev_priv->primary->handle || !dev->agp_buffer_map->handle) { - DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n", - dev_priv->warp->handle, dev_priv->primary->handle, - dev->agp_buffer_map->handle); - return -ENOMEM; - } - - dev_priv->dma_access = MGA_PAGPXFER; - dev_priv->wagp_enable = MGA_WAGP_ENABLE; - - DRM_INFO("Initialized card for AGP DMA.\n"); - return 0; -} -#else -static int mga_do_agp_dma_bootstrap(struct drm_device *dev, - drm_mga_dma_bootstrap_t *dma_bs) -{ - return -EINVAL; -} -#endif - -/* - * Bootstrap the driver for PCI DMA. - * - * \todo - * The algorithm for decreasing the size of the primary DMA buffer could be - * better. The size should be rounded up to the nearest page size, then - * decrease the request size by a single page each pass through the loop. - * - * \todo - * Determine whether the maximum address passed to drm_pci_alloc is correct. - * The same goes for drm_legacy_addbufs_pci. - * - * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap - */ -static int mga_do_pci_dma_bootstrap(struct drm_device *dev, - drm_mga_dma_bootstrap_t *dma_bs) -{ - drm_mga_private_t *const dev_priv = - (drm_mga_private_t *) dev->dev_private; - unsigned int warp_size = MGA_WARP_UCODE_SIZE; - unsigned int primary_size; - unsigned int bin_count; - int err; - struct drm_buf_desc req; - - if (dev->dma == NULL) { - DRM_ERROR("dev->dma is NULL\n"); - return -EFAULT; - } - - /* Make drm_legacy_addbufs happy by not trying to create a mapping for - * less than a page. - */ - if (warp_size < PAGE_SIZE) - warp_size = PAGE_SIZE; - - /* The proper alignment is 0x100 for this mapping */ - err = drm_legacy_addmap(dev, 0, warp_size, _DRM_CONSISTENT, - _DRM_READ_ONLY, &dev_priv->warp); - if (err != 0) { - DRM_ERROR("Unable to create mapping for WARP microcode: %d\n", - err); - return err; - } - - /* Other than the bottom two bits being used to encode other - * information, there don't appear to be any restrictions on the - * alignment of the primary or secondary DMA buffers. - */ - - for (primary_size = dma_bs->primary_size; primary_size != 0; - primary_size >>= 1) { - /* The proper alignment for this mapping is 0x04 */ - err = drm_legacy_addmap(dev, 0, primary_size, _DRM_CONSISTENT, - _DRM_READ_ONLY, &dev_priv->primary); - if (!err) - break; - } - - if (err != 0) { - DRM_ERROR("Unable to allocate primary DMA region: %d\n", err); - return -ENOMEM; - } - - if (dev_priv->primary->size != dma_bs->primary_size) { - DRM_INFO("Primary DMA buffer size reduced from %u to %u.\n", - dma_bs->primary_size, - (unsigned)dev_priv->primary->size); - dma_bs->primary_size = dev_priv->primary->size; - } - - for (bin_count = dma_bs->secondary_bin_count; bin_count > 0; - bin_count--) { - (void)memset(&req, 0, sizeof(req)); - req.count = bin_count; - req.size = dma_bs->secondary_bin_size; - - err = drm_legacy_addbufs_pci(dev, &req); - if (!err) - break; - } - - if (bin_count == 0) { - DRM_ERROR("Unable to add secondary DMA buffers: %d\n", err); - return err; - } - - if (bin_count != dma_bs->secondary_bin_count) { - DRM_INFO("Secondary PCI DMA buffer bin count reduced from %u " - "to %u.\n", dma_bs->secondary_bin_count, bin_count); - - dma_bs->secondary_bin_count = bin_count; - } - - dev_priv->dma_access = 0; - dev_priv->wagp_enable = 0; - - dma_bs->agp_mode = 0; - - DRM_INFO("Initialized card for PCI DMA.\n"); - return 0; -} - -static int mga_do_dma_bootstrap(struct drm_device *dev, - drm_mga_dma_bootstrap_t *dma_bs) -{ - const int is_agp = (dma_bs->agp_mode != 0) && dev->agp; - int err; - drm_mga_private_t *const dev_priv = - (drm_mga_private_t *) dev->dev_private; - - dev_priv->used_new_dma_init = 1; - - /* The first steps are the same for both PCI and AGP based DMA. Map - * the cards MMIO registers and map a status page. - */ - err = drm_legacy_addmap(dev, dev_priv->mmio_base, dev_priv->mmio_size, - _DRM_REGISTERS, _DRM_READ_ONLY, - &dev_priv->mmio); - if (err) { - DRM_ERROR("Unable to map MMIO region: %d\n", err); - return err; - } - - err = drm_legacy_addmap(dev, 0, SAREA_MAX, _DRM_SHM, - _DRM_READ_ONLY | _DRM_LOCKED | _DRM_KERNEL, - &dev_priv->status); - if (err) { - DRM_ERROR("Unable to map status region: %d\n", err); - return err; - } - - /* The DMA initialization procedure is slightly different for PCI and - * AGP cards. AGP cards just allocate a large block of AGP memory and - * carve off portions of it for internal uses. The remaining memory - * is returned to user-mode to be used for AGP textures. - */ - if (is_agp) - err = mga_do_agp_dma_bootstrap(dev, dma_bs); - - /* If we attempted to initialize the card for AGP DMA but failed, - * clean-up any mess that may have been created. - */ - - if (err) - mga_do_cleanup_dma(dev, MINIMAL_CLEANUP); - - /* Not only do we want to try and initialized PCI cards for PCI DMA, - * but we also try to initialized AGP cards that could not be - * initialized for AGP DMA. This covers the case where we have an AGP - * card in a system with an unsupported AGP chipset. In that case the - * card will be detected as AGP, but we won't be able to allocate any - * AGP memory, etc. - */ - - if (!is_agp || err) - err = mga_do_pci_dma_bootstrap(dev, dma_bs); - - return err; -} - -int mga_dma_bootstrap(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_mga_dma_bootstrap_t *bootstrap = data; - int err; - static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 }; - const drm_mga_private_t *const dev_priv = - (drm_mga_private_t *) dev->dev_private; - - err = mga_do_dma_bootstrap(dev, bootstrap); - if (err) { - mga_do_cleanup_dma(dev, FULL_CLEANUP); - return err; - } - - if (dev_priv->agp_textures != NULL) { - bootstrap->texture_handle = dev_priv->agp_textures->offset; - bootstrap->texture_size = dev_priv->agp_textures->size; - } else { - bootstrap->texture_handle = 0; - bootstrap->texture_size = 0; - } - - bootstrap->agp_mode = modes[bootstrap->agp_mode & 0x07]; - - return err; -} - -static int mga_do_init_dma(struct drm_device *dev, drm_mga_init_t *init) -{ - drm_mga_private_t *dev_priv; - int ret; - DRM_DEBUG("\n"); - - dev_priv = dev->dev_private; - - if (init->sgram) - dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK; - else - dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR; - dev_priv->maccess = init->maccess; - - dev_priv->fb_cpp = init->fb_cpp; - dev_priv->front_offset = init->front_offset; - dev_priv->front_pitch = init->front_pitch; - dev_priv->back_offset = init->back_offset; - dev_priv->back_pitch = init->back_pitch; - - dev_priv->depth_cpp = init->depth_cpp; - dev_priv->depth_offset = init->depth_offset; - dev_priv->depth_pitch = init->depth_pitch; - - /* FIXME: Need to support AGP textures... - */ - dev_priv->texture_offset = init->texture_offset[0]; - dev_priv->texture_size = init->texture_size[0]; - - dev_priv->sarea = drm_legacy_getsarea(dev); - if (!dev_priv->sarea) { - DRM_ERROR("failed to find sarea!\n"); - return -EINVAL; - } - - if (!dev_priv->used_new_dma_init) { - - dev_priv->dma_access = MGA_PAGPXFER; - dev_priv->wagp_enable = MGA_WAGP_ENABLE; - - dev_priv->status = drm_legacy_findmap(dev, init->status_offset); - if (!dev_priv->status) { - DRM_ERROR("failed to find status page!\n"); - return -EINVAL; - } - dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset); - if (!dev_priv->mmio) { - DRM_ERROR("failed to find mmio region!\n"); - return -EINVAL; - } - dev_priv->warp = drm_legacy_findmap(dev, init->warp_offset); - if (!dev_priv->warp) { - DRM_ERROR("failed to find warp microcode region!\n"); - return -EINVAL; - } - dev_priv->primary = drm_legacy_findmap(dev, init->primary_offset); - if (!dev_priv->primary) { - DRM_ERROR("failed to find primary dma region!\n"); - return -EINVAL; - } - dev->agp_buffer_token = init->buffers_offset; - dev->agp_buffer_map = - drm_legacy_findmap(dev, init->buffers_offset); - if (!dev->agp_buffer_map) { - DRM_ERROR("failed to find dma buffer region!\n"); - return -EINVAL; - } - - drm_legacy_ioremap(dev_priv->warp, dev); - drm_legacy_ioremap(dev_priv->primary, dev); - drm_legacy_ioremap(dev->agp_buffer_map, dev); - } - - dev_priv->sarea_priv = - (drm_mga_sarea_t *) ((u8 *) dev_priv->sarea->handle + - init->sarea_priv_offset); - - if (!dev_priv->warp->handle || - !dev_priv->primary->handle || - ((dev_priv->dma_access != 0) && - ((dev->agp_buffer_map == NULL) || - (dev->agp_buffer_map->handle == NULL)))) { - DRM_ERROR("failed to ioremap agp regions!\n"); - return -ENOMEM; - } - - ret = mga_warp_install_microcode(dev_priv); - if (ret < 0) { - DRM_ERROR("failed to install WARP ucode!: %d\n", ret); - return ret; - } - - ret = mga_warp_init(dev_priv); - if (ret < 0) { - DRM_ERROR("failed to init WARP engine!: %d\n", ret); - return ret; - } - - dev_priv->prim.status = (u32 *) dev_priv->status->handle; - - mga_do_wait_for_idle(dev_priv); - - /* Init the primary DMA registers. - */ - MGA_WRITE(MGA_PRIMADDRESS, dev_priv->primary->offset | MGA_DMA_GENERAL); -#if 0 - MGA_WRITE(MGA_PRIMPTR, virt_to_bus((void *)dev_priv->prim.status) | MGA_PRIMPTREN0 | /* Soft trap, SECEND, SETUPEND */ - MGA_PRIMPTREN1); /* DWGSYNC */ -#endif - - dev_priv->prim.start = (u8 *) dev_priv->primary->handle; - dev_priv->prim.end = ((u8 *) dev_priv->primary->handle - + dev_priv->primary->size); - dev_priv->prim.size = dev_priv->primary->size; - - dev_priv->prim.tail = 0; - dev_priv->prim.space = dev_priv->prim.size; - dev_priv->prim.wrapped = 0; - - dev_priv->prim.last_flush = 0; - dev_priv->prim.last_wrap = 0; - - dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE; - - dev_priv->prim.status[0] = dev_priv->primary->offset; - dev_priv->prim.status[1] = 0; - - dev_priv->sarea_priv->last_wrap = 0; - dev_priv->sarea_priv->last_frame.head = 0; - dev_priv->sarea_priv->last_frame.wrap = 0; - - if (mga_freelist_init(dev, dev_priv) < 0) { - DRM_ERROR("could not initialize freelist\n"); - return -ENOMEM; - } - - return 0; -} - -static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup) -{ - int err = 0; - DRM_DEBUG("\n"); - - /* Make sure interrupts are disabled here because the uninstall ioctl - * may not have been called from userspace and after dev_private - * is freed, it's too late. - */ - if (dev->irq_enabled) - drm_legacy_irq_uninstall(dev); - - if (dev->dev_private) { - drm_mga_private_t *dev_priv = dev->dev_private; - - if ((dev_priv->warp != NULL) - && (dev_priv->warp->type != _DRM_CONSISTENT)) - drm_legacy_ioremapfree(dev_priv->warp, dev); - - if ((dev_priv->primary != NULL) - && (dev_priv->primary->type != _DRM_CONSISTENT)) - drm_legacy_ioremapfree(dev_priv->primary, dev); - - if (dev->agp_buffer_map != NULL) - drm_legacy_ioremapfree(dev->agp_buffer_map, dev); - - if (dev_priv->used_new_dma_init) { -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->agp_handle != 0) { - struct drm_agp_binding unbind_req; - struct drm_agp_buffer free_req; - - unbind_req.handle = dev_priv->agp_handle; - drm_legacy_agp_unbind(dev, &unbind_req); - - free_req.handle = dev_priv->agp_handle; - drm_legacy_agp_free(dev, &free_req); - - dev_priv->agp_textures = NULL; - dev_priv->agp_size = 0; - dev_priv->agp_handle = 0; - } - - if ((dev->agp != NULL) && dev->agp->acquired) - err = drm_legacy_agp_release(dev); -#endif - } - - dev_priv->warp = NULL; - dev_priv->primary = NULL; - dev_priv->sarea = NULL; - dev_priv->sarea_priv = NULL; - dev->agp_buffer_map = NULL; - - if (full_cleanup) { - dev_priv->mmio = NULL; - dev_priv->status = NULL; - dev_priv->used_new_dma_init = 0; - } - - memset(&dev_priv->prim, 0, sizeof(dev_priv->prim)); - dev_priv->warp_pipe = 0; - memset(dev_priv->warp_pipe_phys, 0, - sizeof(dev_priv->warp_pipe_phys)); - - if (dev_priv->head != NULL) - mga_freelist_cleanup(dev); - } - - return err; -} - -int mga_dma_init(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_mga_init_t *init = data; - int err; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - switch (init->func) { - case MGA_INIT_DMA: - err = mga_do_init_dma(dev, init); - if (err) - (void)mga_do_cleanup_dma(dev, FULL_CLEANUP); - return err; - case MGA_CLEANUP_DMA: - return mga_do_cleanup_dma(dev, FULL_CLEANUP); - } - - return -EINVAL; -} - -/* ================================================================ - * Primary DMA stream management - */ - -int mga_dma_flush(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - struct drm_lock *lock = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DRM_DEBUG("%s%s%s\n", - (lock->flags & _DRM_LOCK_FLUSH) ? "flush, " : "", - (lock->flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "", - (lock->flags & _DRM_LOCK_QUIESCENT) ? "idle, " : ""); - - WRAP_WAIT_WITH_RETURN(dev_priv); - - if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) - mga_do_dma_flush(dev_priv); - - if (lock->flags & _DRM_LOCK_QUIESCENT) { -#if MGA_DMA_DEBUG - int ret = mga_do_wait_for_idle(dev_priv); - if (ret < 0) - DRM_INFO("-EBUSY\n"); - return ret; -#else - return mga_do_wait_for_idle(dev_priv); -#endif - } else { - return 0; - } -} - -int mga_dma_reset(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - return mga_do_dma_reset(dev_priv); -} - -/* ================================================================ - * DMA buffer management - */ - -static int mga_dma_get_buffers(struct drm_device *dev, - struct drm_file *file_priv, struct drm_dma *d) -{ - struct drm_buf *buf; - int i; - - for (i = d->granted_count; i < d->request_count; i++) { - buf = mga_freelist_get(dev); - if (!buf) - return -EAGAIN; - - buf->file_priv = file_priv; - - if (copy_to_user(&d->request_indices[i], - &buf->idx, sizeof(buf->idx))) - return -EFAULT; - if (copy_to_user(&d->request_sizes[i], - &buf->total, sizeof(buf->total))) - return -EFAULT; - - d->granted_count++; - } - return 0; -} - -int mga_dma_buffers(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - struct drm_dma *d = data; - int ret = 0; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - /* Please don't send us buffers. - */ - if (d->send_count != 0) { - DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - task_pid_nr(current), d->send_count); - return -EINVAL; - } - - /* We'll send you buffers. - */ - if (d->request_count < 0 || d->request_count > dma->buf_count) { - DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - task_pid_nr(current), d->request_count, - dma->buf_count); - return -EINVAL; - } - - WRAP_TEST_WITH_RETURN(dev_priv); - - d->granted_count = 0; - - if (d->request_count) - ret = mga_dma_get_buffers(dev, file_priv, d); - - return ret; -} - -/* - * Called just before the module is unloaded. - */ -void mga_driver_unload(struct drm_device *dev) -{ - kfree(dev->dev_private); - dev->dev_private = NULL; -} - -/* - * Called when the last opener of the device is closed. - */ -void mga_driver_lastclose(struct drm_device *dev) -{ - mga_do_cleanup_dma(dev, FULL_CLEANUP); -} - -int mga_driver_dma_quiescent(struct drm_device *dev) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - return mga_do_wait_for_idle(dev_priv); -} diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c deleted file mode 100644 index 71128e6f6ae9..000000000000 --- a/drivers/gpu/drm/mga/mga_drv.c +++ /dev/null @@ -1,104 +0,0 @@ -/* mga_drv.c -- Matrox G200/G400 driver -*- linux-c -*- - * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Rickard E. (Rik) Faith - * Gareth Hughes - */ - -#include - -#include -#include - -#include "mga_drv.h" - -static struct pci_device_id pciidlist[] = { - mga_PCI_IDS -}; - -static const struct file_operations mga_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = drm_legacy_mmap, - .poll = drm_poll, -#ifdef CONFIG_COMPAT - .compat_ioctl = mga_compat_ioctl, -#endif - .llseek = noop_llseek, -}; - -static struct drm_driver driver = { - .driver_features = - DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_LEGACY | - DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ, - .dev_priv_size = sizeof(drm_mga_buf_priv_t), - .load = mga_driver_load, - .unload = mga_driver_unload, - .lastclose = mga_driver_lastclose, - .dma_quiescent = mga_driver_dma_quiescent, - .get_vblank_counter = mga_get_vblank_counter, - .enable_vblank = mga_enable_vblank, - .disable_vblank = mga_disable_vblank, - .irq_preinstall = mga_driver_irq_preinstall, - .irq_postinstall = mga_driver_irq_postinstall, - .irq_uninstall = mga_driver_irq_uninstall, - .irq_handler = mga_driver_irq_handler, - .ioctls = mga_ioctls, - .dma_ioctl = mga_dma_buffers, - .fops = &mga_driver_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; - -static struct pci_driver mga_pci_driver = { - .name = DRIVER_NAME, - .id_table = pciidlist, -}; - -static int __init mga_init(void) -{ - driver.num_ioctls = mga_max_ioctl; - return drm_legacy_pci_init(&driver, &mga_pci_driver); -} - -static void __exit mga_exit(void) -{ - drm_legacy_pci_exit(&driver, &mga_pci_driver); -} - -module_init(mga_init); -module_exit(mga_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h deleted file mode 100644 index f61401c70b90..000000000000 --- a/drivers/gpu/drm/mga/mga_drv.h +++ /dev/null @@ -1,685 +0,0 @@ -/* mga_drv.h -- Private header for the Matrox G200/G400 driver -*- linux-c -*- - * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Gareth Hughes - */ - -#ifndef __MGA_DRV_H__ -#define __MGA_DRV_H__ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* General customization: - */ - -#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." - -#define DRIVER_NAME "mga" -#define DRIVER_DESC "Matrox G200/G400" -#define DRIVER_DATE "20051102" - -#define DRIVER_MAJOR 3 -#define DRIVER_MINOR 2 -#define DRIVER_PATCHLEVEL 1 - -typedef struct drm_mga_primary_buffer { - u8 *start; - u8 *end; - int size; - - u32 tail; - int space; - volatile long wrapped; - - volatile u32 *status; - - u32 last_flush; - u32 last_wrap; - - u32 high_mark; -} drm_mga_primary_buffer_t; - -typedef struct drm_mga_freelist { - struct drm_mga_freelist *next; - struct drm_mga_freelist *prev; - drm_mga_age_t age; - struct drm_buf *buf; -} drm_mga_freelist_t; - -typedef struct { - drm_mga_freelist_t *list_entry; - int discard; - int dispatched; -} drm_mga_buf_priv_t; - -typedef struct drm_mga_private { - drm_mga_primary_buffer_t prim; - drm_mga_sarea_t *sarea_priv; - - drm_mga_freelist_t *head; - drm_mga_freelist_t *tail; - - unsigned int warp_pipe; - unsigned long warp_pipe_phys[MGA_MAX_WARP_PIPES]; - - int chipset; - int usec_timeout; - - /** - * If set, the new DMA initialization sequence was used. This is - * primarilly used to select how the driver should uninitialized its - * internal DMA structures. - */ - int used_new_dma_init; - - /** - * If AGP memory is used for DMA buffers, this will be the value - * \c MGA_PAGPXFER. Otherwise, it will be zero (for a PCI transfer). - */ - u32 dma_access; - - /** - * If AGP memory is used for DMA buffers, this will be the value - * \c MGA_WAGP_ENABLE. Otherwise, it will be zero (for a PCI - * transfer). - */ - u32 wagp_enable; - - /** - * \name MMIO region parameters. - * - * \sa drm_mga_private_t::mmio - */ - /*@{ */ - resource_size_t mmio_base; /**< Bus address of base of MMIO. */ - resource_size_t mmio_size; /**< Size of the MMIO region. */ - /*@} */ - - u32 clear_cmd; - u32 maccess; - - atomic_t vbl_received; /**< Number of vblanks received. */ - wait_queue_head_t fence_queue; - atomic_t last_fence_retired; - u32 next_fence_to_post; - - unsigned int fb_cpp; - unsigned int front_offset; - unsigned int front_pitch; - unsigned int back_offset; - unsigned int back_pitch; - - unsigned int depth_cpp; - unsigned int depth_offset; - unsigned int depth_pitch; - - unsigned int texture_offset; - unsigned int texture_size; - - drm_local_map_t *sarea; - drm_local_map_t *mmio; - drm_local_map_t *status; - drm_local_map_t *warp; - drm_local_map_t *primary; - drm_local_map_t *agp_textures; - - unsigned long agp_handle; - unsigned int agp_size; -} drm_mga_private_t; - -extern const struct drm_ioctl_desc mga_ioctls[]; -extern int mga_max_ioctl; - - /* mga_dma.c */ -extern int mga_dma_bootstrap(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int mga_dma_init(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int mga_getparam(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int mga_dma_flush(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int mga_dma_reset(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int mga_dma_buffers(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int mga_driver_load(struct drm_device *dev, unsigned long flags); -extern void mga_driver_unload(struct drm_device *dev); -extern void mga_driver_lastclose(struct drm_device *dev); -extern int mga_driver_dma_quiescent(struct drm_device *dev); - -extern int mga_do_wait_for_idle(drm_mga_private_t *dev_priv); - -extern void mga_do_dma_flush(drm_mga_private_t *dev_priv); -extern void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv); -extern void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv); - -extern int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf); - - /* mga_warp.c */ -extern int mga_warp_install_microcode(drm_mga_private_t *dev_priv); -extern int mga_warp_init(drm_mga_private_t *dev_priv); - - /* mga_irq.c */ -extern int mga_enable_vblank(struct drm_device *dev, unsigned int pipe); -extern void mga_disable_vblank(struct drm_device *dev, unsigned int pipe); -extern u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe); -extern void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence); -extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence); -extern irqreturn_t mga_driver_irq_handler(int irq, void *arg); -extern void mga_driver_irq_preinstall(struct drm_device *dev); -extern int mga_driver_irq_postinstall(struct drm_device *dev); -extern void mga_driver_irq_uninstall(struct drm_device *dev); -extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg); - -#define mga_flush_write_combine() wmb() - -#define MGA_READ8(reg) \ - readb(((void __iomem *)dev_priv->mmio->handle) + (reg)) -#define MGA_READ(reg) \ - readl(((void __iomem *)dev_priv->mmio->handle) + (reg)) -#define MGA_WRITE8(reg, val) \ - writeb(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) -#define MGA_WRITE(reg, val) \ - writel(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) - -#define DWGREG0 0x1c00 -#define DWGREG0_END 0x1dff -#define DWGREG1 0x2c00 -#define DWGREG1_END 0x2dff - -#define ISREG0(r) (r >= DWGREG0 && r <= DWGREG0_END) -#define DMAREG0(r) (u8)((r - DWGREG0) >> 2) -#define DMAREG1(r) (u8)(((r - DWGREG1) >> 2) | 0x80) -#define DMAREG(r) (ISREG0(r) ? DMAREG0(r) : DMAREG1(r)) - -/* ================================================================ - * Helper macross... - */ - -#define MGA_EMIT_STATE(dev_priv, dirty) \ -do { \ - if ((dirty) & ~MGA_UPLOAD_CLIPRECTS) { \ - if (dev_priv->chipset >= MGA_CARD_TYPE_G400) \ - mga_g400_emit_state(dev_priv); \ - else \ - mga_g200_emit_state(dev_priv); \ - } \ -} while (0) - -#define WRAP_TEST_WITH_RETURN(dev_priv) \ -do { \ - if (test_bit(0, &dev_priv->prim.wrapped)) { \ - if (mga_is_idle(dev_priv)) { \ - mga_do_dma_wrap_end(dev_priv); \ - } else if (dev_priv->prim.space < \ - dev_priv->prim.high_mark) { \ - if (MGA_DMA_DEBUG) \ - DRM_INFO("wrap...\n"); \ - return -EBUSY; \ - } \ - } \ -} while (0) - -#define WRAP_WAIT_WITH_RETURN(dev_priv) \ -do { \ - if (test_bit(0, &dev_priv->prim.wrapped)) { \ - if (mga_do_wait_for_idle(dev_priv) < 0) { \ - if (MGA_DMA_DEBUG) \ - DRM_INFO("wrap...\n"); \ - return -EBUSY; \ - } \ - mga_do_dma_wrap_end(dev_priv); \ - } \ -} while (0) - -/* ================================================================ - * Primary DMA command stream - */ - -#define MGA_VERBOSE 0 - -#define DMA_LOCALS unsigned int write; volatile u8 *prim; - -#define DMA_BLOCK_SIZE (5 * sizeof(u32)) - -#define BEGIN_DMA(n) \ -do { \ - if (MGA_VERBOSE) { \ - DRM_INFO("BEGIN_DMA(%d)\n", (n)); \ - DRM_INFO(" space=0x%x req=0x%zx\n", \ - dev_priv->prim.space, (n) * DMA_BLOCK_SIZE); \ - } \ - prim = dev_priv->prim.start; \ - write = dev_priv->prim.tail; \ -} while (0) - -#define BEGIN_DMA_WRAP() \ -do { \ - if (MGA_VERBOSE) { \ - DRM_INFO("BEGIN_DMA()\n"); \ - DRM_INFO(" space=0x%x\n", dev_priv->prim.space); \ - } \ - prim = dev_priv->prim.start; \ - write = dev_priv->prim.tail; \ -} while (0) - -#define ADVANCE_DMA() \ -do { \ - dev_priv->prim.tail = write; \ - if (MGA_VERBOSE) \ - DRM_INFO("ADVANCE_DMA() tail=0x%05x sp=0x%x\n", \ - write, dev_priv->prim.space); \ -} while (0) - -#define FLUSH_DMA() \ -do { \ - if (0) { \ - DRM_INFO("\n"); \ - DRM_INFO(" tail=0x%06x head=0x%06lx\n", \ - dev_priv->prim.tail, \ - (unsigned long)(MGA_READ(MGA_PRIMADDRESS) - \ - dev_priv->primary->offset)); \ - } \ - if (!test_bit(0, &dev_priv->prim.wrapped)) { \ - if (dev_priv->prim.space < dev_priv->prim.high_mark) \ - mga_do_dma_wrap_start(dev_priv); \ - else \ - mga_do_dma_flush(dev_priv); \ - } \ -} while (0) - -/* Never use this, always use DMA_BLOCK(...) for primary DMA output. - */ -#define DMA_WRITE(offset, val) \ -do { \ - if (MGA_VERBOSE) \ - DRM_INFO(" DMA_WRITE( 0x%08x ) at 0x%04zx\n", \ - (u32)(val), write + (offset) * sizeof(u32)); \ - *(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val; \ -} while (0) - -#define DMA_BLOCK(reg0, val0, reg1, val1, reg2, val2, reg3, val3) \ -do { \ - DMA_WRITE(0, ((DMAREG(reg0) << 0) | \ - (DMAREG(reg1) << 8) | \ - (DMAREG(reg2) << 16) | \ - (DMAREG(reg3) << 24))); \ - DMA_WRITE(1, val0); \ - DMA_WRITE(2, val1); \ - DMA_WRITE(3, val2); \ - DMA_WRITE(4, val3); \ - write += DMA_BLOCK_SIZE; \ -} while (0) - -/* Buffer aging via primary DMA stream head pointer. - */ - -#define SET_AGE(age, h, w) \ -do { \ - (age)->head = h; \ - (age)->wrap = w; \ -} while (0) - -#define TEST_AGE(age, h, w) ((age)->wrap < w || \ - ((age)->wrap == w && \ - (age)->head < h)) - -#define AGE_BUFFER(buf_priv) \ -do { \ - drm_mga_freelist_t *entry = (buf_priv)->list_entry; \ - if ((buf_priv)->dispatched) { \ - entry->age.head = (dev_priv->prim.tail + \ - dev_priv->primary->offset); \ - entry->age.wrap = dev_priv->sarea_priv->last_wrap; \ - } else { \ - entry->age.head = 0; \ - entry->age.wrap = 0; \ - } \ -} while (0) - -#define MGA_ENGINE_IDLE_MASK (MGA_SOFTRAPEN | \ - MGA_DWGENGSTS | \ - MGA_ENDPRDMASTS) -#define MGA_DMA_IDLE_MASK (MGA_SOFTRAPEN | \ - MGA_ENDPRDMASTS) - -#define MGA_DMA_DEBUG 0 - -/* A reduced set of the mga registers. - */ -#define MGA_CRTC_INDEX 0x1fd4 -#define MGA_CRTC_DATA 0x1fd5 - -/* CRTC11 */ -#define MGA_VINTCLR (1 << 4) -#define MGA_VINTEN (1 << 5) - -#define MGA_ALPHACTRL 0x2c7c -#define MGA_AR0 0x1c60 -#define MGA_AR1 0x1c64 -#define MGA_AR2 0x1c68 -#define MGA_AR3 0x1c6c -#define MGA_AR4 0x1c70 -#define MGA_AR5 0x1c74 -#define MGA_AR6 0x1c78 - -#define MGA_CXBNDRY 0x1c80 -#define MGA_CXLEFT 0x1ca0 -#define MGA_CXRIGHT 0x1ca4 - -#define MGA_DMAPAD 0x1c54 -#define MGA_DSTORG 0x2cb8 -#define MGA_DWGCTL 0x1c00 -# define MGA_OPCOD_MASK (15 << 0) -# define MGA_OPCOD_TRAP (4 << 0) -# define MGA_OPCOD_TEXTURE_TRAP (6 << 0) -# define MGA_OPCOD_BITBLT (8 << 0) -# define MGA_OPCOD_ILOAD (9 << 0) -# define MGA_ATYPE_MASK (7 << 4) -# define MGA_ATYPE_RPL (0 << 4) -# define MGA_ATYPE_RSTR (1 << 4) -# define MGA_ATYPE_ZI (3 << 4) -# define MGA_ATYPE_BLK (4 << 4) -# define MGA_ATYPE_I (7 << 4) -# define MGA_LINEAR (1 << 7) -# define MGA_ZMODE_MASK (7 << 8) -# define MGA_ZMODE_NOZCMP (0 << 8) -# define MGA_ZMODE_ZE (2 << 8) -# define MGA_ZMODE_ZNE (3 << 8) -# define MGA_ZMODE_ZLT (4 << 8) -# define MGA_ZMODE_ZLTE (5 << 8) -# define MGA_ZMODE_ZGT (6 << 8) -# define MGA_ZMODE_ZGTE (7 << 8) -# define MGA_SOLID (1 << 11) -# define MGA_ARZERO (1 << 12) -# define MGA_SGNZERO (1 << 13) -# define MGA_SHIFTZERO (1 << 14) -# define MGA_BOP_MASK (15 << 16) -# define MGA_BOP_ZERO (0 << 16) -# define MGA_BOP_DST (10 << 16) -# define MGA_BOP_SRC (12 << 16) -# define MGA_BOP_ONE (15 << 16) -# define MGA_TRANS_SHIFT 20 -# define MGA_TRANS_MASK (15 << 20) -# define MGA_BLTMOD_MASK (15 << 25) -# define MGA_BLTMOD_BMONOLEF (0 << 25) -# define MGA_BLTMOD_BMONOWF (4 << 25) -# define MGA_BLTMOD_PLAN (1 << 25) -# define MGA_BLTMOD_BFCOL (2 << 25) -# define MGA_BLTMOD_BU32BGR (3 << 25) -# define MGA_BLTMOD_BU32RGB (7 << 25) -# define MGA_BLTMOD_BU24BGR (11 << 25) -# define MGA_BLTMOD_BU24RGB (15 << 25) -# define MGA_PATTERN (1 << 29) -# define MGA_TRANSC (1 << 30) -# define MGA_CLIPDIS (1 << 31) -#define MGA_DWGSYNC 0x2c4c - -#define MGA_FCOL 0x1c24 -#define MGA_FIFOSTATUS 0x1e10 -#define MGA_FOGCOL 0x1cf4 -#define MGA_FXBNDRY 0x1c84 -#define MGA_FXLEFT 0x1ca8 -#define MGA_FXRIGHT 0x1cac - -#define MGA_ICLEAR 0x1e18 -# define MGA_SOFTRAPICLR (1 << 0) -# define MGA_VLINEICLR (1 << 5) -#define MGA_IEN 0x1e1c -# define MGA_SOFTRAPIEN (1 << 0) -# define MGA_VLINEIEN (1 << 5) - -#define MGA_LEN 0x1c5c - -#define MGA_MACCESS 0x1c04 - -#define MGA_PITCH 0x1c8c -#define MGA_PLNWT 0x1c1c -#define MGA_PRIMADDRESS 0x1e58 -# define MGA_DMA_GENERAL (0 << 0) -# define MGA_DMA_BLIT (1 << 0) -# define MGA_DMA_VECTOR (2 << 0) -# define MGA_DMA_VERTEX (3 << 0) -#define MGA_PRIMEND 0x1e5c -# define MGA_PRIMNOSTART (1 << 0) -# define MGA_PAGPXFER (1 << 1) -#define MGA_PRIMPTR 0x1e50 -# define MGA_PRIMPTREN0 (1 << 0) -# define MGA_PRIMPTREN1 (1 << 1) - -#define MGA_RST 0x1e40 -# define MGA_SOFTRESET (1 << 0) -# define MGA_SOFTEXTRST (1 << 1) - -#define MGA_SECADDRESS 0x2c40 -#define MGA_SECEND 0x2c44 -#define MGA_SETUPADDRESS 0x2cd0 -#define MGA_SETUPEND 0x2cd4 -#define MGA_SGN 0x1c58 -#define MGA_SOFTRAP 0x2c48 -#define MGA_SRCORG 0x2cb4 -# define MGA_SRMMAP_MASK (1 << 0) -# define MGA_SRCMAP_FB (0 << 0) -# define MGA_SRCMAP_SYSMEM (1 << 0) -# define MGA_SRCACC_MASK (1 << 1) -# define MGA_SRCACC_PCI (0 << 1) -# define MGA_SRCACC_AGP (1 << 1) -#define MGA_STATUS 0x1e14 -# define MGA_SOFTRAPEN (1 << 0) -# define MGA_VSYNCPEN (1 << 4) -# define MGA_VLINEPEN (1 << 5) -# define MGA_DWGENGSTS (1 << 16) -# define MGA_ENDPRDMASTS (1 << 17) -#define MGA_STENCIL 0x2cc8 -#define MGA_STENCILCTL 0x2ccc - -#define MGA_TDUALSTAGE0 0x2cf8 -#define MGA_TDUALSTAGE1 0x2cfc -#define MGA_TEXBORDERCOL 0x2c5c -#define MGA_TEXCTL 0x2c30 -#define MGA_TEXCTL2 0x2c3c -# define MGA_DUALTEX (1 << 7) -# define MGA_G400_TC2_MAGIC (1 << 15) -# define MGA_MAP1_ENABLE (1 << 31) -#define MGA_TEXFILTER 0x2c58 -#define MGA_TEXHEIGHT 0x2c2c -#define MGA_TEXORG 0x2c24 -# define MGA_TEXORGMAP_MASK (1 << 0) -# define MGA_TEXORGMAP_FB (0 << 0) -# define MGA_TEXORGMAP_SYSMEM (1 << 0) -# define MGA_TEXORGACC_MASK (1 << 1) -# define MGA_TEXORGACC_PCI (0 << 1) -# define MGA_TEXORGACC_AGP (1 << 1) -#define MGA_TEXORG1 0x2ca4 -#define MGA_TEXORG2 0x2ca8 -#define MGA_TEXORG3 0x2cac -#define MGA_TEXORG4 0x2cb0 -#define MGA_TEXTRANS 0x2c34 -#define MGA_TEXTRANSHIGH 0x2c38 -#define MGA_TEXWIDTH 0x2c28 - -#define MGA_WACCEPTSEQ 0x1dd4 -#define MGA_WCODEADDR 0x1e6c -#define MGA_WFLAG 0x1dc4 -#define MGA_WFLAG1 0x1de0 -#define MGA_WFLAGNB 0x1e64 -#define MGA_WFLAGNB1 0x1e08 -#define MGA_WGETMSB 0x1dc8 -#define MGA_WIADDR 0x1dc0 -#define MGA_WIADDR2 0x1dd8 -# define MGA_WMODE_SUSPEND (0 << 0) -# define MGA_WMODE_RESUME (1 << 0) -# define MGA_WMODE_JUMP (2 << 0) -# define MGA_WMODE_START (3 << 0) -# define MGA_WAGP_ENABLE (1 << 2) -#define MGA_WMISC 0x1e70 -# define MGA_WUCODECACHE_ENABLE (1 << 0) -# define MGA_WMASTER_ENABLE (1 << 1) -# define MGA_WCACHEFLUSH_ENABLE (1 << 3) -#define MGA_WVRTXSZ 0x1dcc - -#define MGA_YBOT 0x1c9c -#define MGA_YDST 0x1c90 -#define MGA_YDSTLEN 0x1c88 -#define MGA_YDSTORG 0x1c94 -#define MGA_YTOP 0x1c98 - -#define MGA_ZORG 0x1c0c - -/* This finishes the current batch of commands - */ -#define MGA_EXEC 0x0100 - -/* AGP PLL encoding (for G200 only). - */ -#define MGA_AGP_PLL 0x1e4c -# define MGA_AGP2XPLL_DISABLE (0 << 0) -# define MGA_AGP2XPLL_ENABLE (1 << 0) - -/* Warp registers - */ -#define MGA_WR0 0x2d00 -#define MGA_WR1 0x2d04 -#define MGA_WR2 0x2d08 -#define MGA_WR3 0x2d0c -#define MGA_WR4 0x2d10 -#define MGA_WR5 0x2d14 -#define MGA_WR6 0x2d18 -#define MGA_WR7 0x2d1c -#define MGA_WR8 0x2d20 -#define MGA_WR9 0x2d24 -#define MGA_WR10 0x2d28 -#define MGA_WR11 0x2d2c -#define MGA_WR12 0x2d30 -#define MGA_WR13 0x2d34 -#define MGA_WR14 0x2d38 -#define MGA_WR15 0x2d3c -#define MGA_WR16 0x2d40 -#define MGA_WR17 0x2d44 -#define MGA_WR18 0x2d48 -#define MGA_WR19 0x2d4c -#define MGA_WR20 0x2d50 -#define MGA_WR21 0x2d54 -#define MGA_WR22 0x2d58 -#define MGA_WR23 0x2d5c -#define MGA_WR24 0x2d60 -#define MGA_WR25 0x2d64 -#define MGA_WR26 0x2d68 -#define MGA_WR27 0x2d6c -#define MGA_WR28 0x2d70 -#define MGA_WR29 0x2d74 -#define MGA_WR30 0x2d78 -#define MGA_WR31 0x2d7c -#define MGA_WR32 0x2d80 -#define MGA_WR33 0x2d84 -#define MGA_WR34 0x2d88 -#define MGA_WR35 0x2d8c -#define MGA_WR36 0x2d90 -#define MGA_WR37 0x2d94 -#define MGA_WR38 0x2d98 -#define MGA_WR39 0x2d9c -#define MGA_WR40 0x2da0 -#define MGA_WR41 0x2da4 -#define MGA_WR42 0x2da8 -#define MGA_WR43 0x2dac -#define MGA_WR44 0x2db0 -#define MGA_WR45 0x2db4 -#define MGA_WR46 0x2db8 -#define MGA_WR47 0x2dbc -#define MGA_WR48 0x2dc0 -#define MGA_WR49 0x2dc4 -#define MGA_WR50 0x2dc8 -#define MGA_WR51 0x2dcc -#define MGA_WR52 0x2dd0 -#define MGA_WR53 0x2dd4 -#define MGA_WR54 0x2dd8 -#define MGA_WR55 0x2ddc -#define MGA_WR56 0x2de0 -#define MGA_WR57 0x2de4 -#define MGA_WR58 0x2de8 -#define MGA_WR59 0x2dec -#define MGA_WR60 0x2df0 -#define MGA_WR61 0x2df4 -#define MGA_WR62 0x2df8 -#define MGA_WR63 0x2dfc -# define MGA_G400_WR_MAGIC (1 << 6) -# define MGA_G400_WR56_MAGIC 0x46480000 /* 12800.0f */ - -#define MGA_ILOAD_ALIGN 64 -#define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1) - -#define MGA_DWGCTL_FLUSH (MGA_OPCOD_TEXTURE_TRAP | \ - MGA_ATYPE_I | \ - MGA_ZMODE_NOZCMP | \ - MGA_ARZERO | \ - MGA_SGNZERO | \ - MGA_BOP_SRC | \ - (15 << MGA_TRANS_SHIFT)) - -#define MGA_DWGCTL_CLEAR (MGA_OPCOD_TRAP | \ - MGA_ZMODE_NOZCMP | \ - MGA_SOLID | \ - MGA_ARZERO | \ - MGA_SGNZERO | \ - MGA_SHIFTZERO | \ - MGA_BOP_SRC | \ - (0 << MGA_TRANS_SHIFT) | \ - MGA_BLTMOD_BMONOLEF | \ - MGA_TRANSC | \ - MGA_CLIPDIS) - -#define MGA_DWGCTL_COPY (MGA_OPCOD_BITBLT | \ - MGA_ATYPE_RPL | \ - MGA_SGNZERO | \ - MGA_SHIFTZERO | \ - MGA_BOP_SRC | \ - (0 << MGA_TRANS_SHIFT) | \ - MGA_BLTMOD_BFCOL | \ - MGA_CLIPDIS) - -/* Simple idle test. - */ -static __inline__ int mga_is_idle(drm_mga_private_t *dev_priv) -{ - u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; - return (status == MGA_ENDPRDMASTS); -} - -#endif diff --git a/drivers/gpu/drm/mga/mga_ioc32.c b/drivers/gpu/drm/mga/mga_ioc32.c deleted file mode 100644 index 894472921c30..000000000000 --- a/drivers/gpu/drm/mga/mga_ioc32.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * \file mga_ioc32.c - * - * 32-bit ioctl compatibility routines for the MGA DRM. - * - * \author Dave Airlie with code from patches by Egbert Eich - * - * - * Copyright (C) Paul Mackerras 2005 - * Copyright (C) Egbert Eich 2003,2004 - * Copyright (C) Dave Airlie 2005 - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include "mga_drv.h" - -typedef struct drm32_mga_init { - int func; - u32 sarea_priv_offset; - struct_group(always32bit, - int chipset; - int sgram; - unsigned int maccess; - unsigned int fb_cpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - unsigned int depth_cpp; - unsigned int depth_offset, depth_pitch; - unsigned int texture_offset[MGA_NR_TEX_HEAPS]; - unsigned int texture_size[MGA_NR_TEX_HEAPS]; - ); - u32 fb_offset; - u32 mmio_offset; - u32 status_offset; - u32 warp_offset; - u32 primary_offset; - u32 buffers_offset; -} drm_mga_init32_t; - -static int compat_mga_init(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_mga_init32_t init32; - drm_mga_init_t init; - - if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) - return -EFAULT; - - init.func = init32.func; - init.sarea_priv_offset = init32.sarea_priv_offset; - memcpy(&init.always32bit, &init32.always32bit, - sizeof(init32.always32bit)); - init.fb_offset = init32.fb_offset; - init.mmio_offset = init32.mmio_offset; - init.status_offset = init32.status_offset; - init.warp_offset = init32.warp_offset; - init.primary_offset = init32.primary_offset; - init.buffers_offset = init32.buffers_offset; - - return drm_ioctl_kernel(file, mga_dma_init, &init, - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); -} - -typedef struct drm_mga_getparam32 { - int param; - u32 value; -} drm_mga_getparam32_t; - -static int compat_mga_getparam(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_mga_getparam32_t getparam32; - drm_mga_getparam_t getparam; - - if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) - return -EFAULT; - - getparam.param = getparam32.param; - getparam.value = compat_ptr(getparam32.value); - return drm_ioctl_kernel(file, mga_getparam, &getparam, DRM_AUTH); -} - -typedef struct drm_mga_drm_bootstrap32 { - u32 texture_handle; - u32 texture_size; - u32 primary_size; - u32 secondary_bin_count; - u32 secondary_bin_size; - u32 agp_mode; - u8 agp_size; -} drm_mga_dma_bootstrap32_t; - -static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_mga_dma_bootstrap32_t dma_bootstrap32; - drm_mga_dma_bootstrap_t dma_bootstrap; - int err; - - if (copy_from_user(&dma_bootstrap32, (void __user *)arg, - sizeof(dma_bootstrap32))) - return -EFAULT; - - dma_bootstrap.texture_handle = dma_bootstrap32.texture_handle; - dma_bootstrap.texture_size = dma_bootstrap32.texture_size; - dma_bootstrap.primary_size = dma_bootstrap32.primary_size; - dma_bootstrap.secondary_bin_count = dma_bootstrap32.secondary_bin_count; - dma_bootstrap.secondary_bin_size = dma_bootstrap32.secondary_bin_size; - dma_bootstrap.agp_mode = dma_bootstrap32.agp_mode; - dma_bootstrap.agp_size = dma_bootstrap32.agp_size; - - err = drm_ioctl_kernel(file, mga_dma_bootstrap, &dma_bootstrap, - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); - if (err) - return err; - - dma_bootstrap32.texture_handle = dma_bootstrap.texture_handle; - dma_bootstrap32.texture_size = dma_bootstrap.texture_size; - dma_bootstrap32.primary_size = dma_bootstrap.primary_size; - dma_bootstrap32.secondary_bin_count = dma_bootstrap.secondary_bin_count; - dma_bootstrap32.secondary_bin_size = dma_bootstrap.secondary_bin_size; - dma_bootstrap32.agp_mode = dma_bootstrap.agp_mode; - dma_bootstrap32.agp_size = dma_bootstrap.agp_size; - if (copy_to_user((void __user *)arg, &dma_bootstrap32, - sizeof(dma_bootstrap32))) - return -EFAULT; - - return 0; -} - -static struct { - drm_ioctl_compat_t *fn; - char *name; -} mga_compat_ioctls[] = { -#define DRM_IOCTL32_DEF(n, f)[DRM_##n] = {.fn = f, .name = #n} - DRM_IOCTL32_DEF(MGA_INIT, compat_mga_init), - DRM_IOCTL32_DEF(MGA_GETPARAM, compat_mga_getparam), - DRM_IOCTL32_DEF(MGA_DMA_BOOTSTRAP, compat_mga_dma_bootstrap), -}; - -/** - * mga_compat_ioctl - Called whenever a 32-bit process running under - * a 64-bit kernel performs an ioctl on /dev/dri/card. - * - * @filp: file pointer. - * @cmd: command. - * @arg: user argument. - * return: zero on success or negative number on failure. - */ -long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - unsigned int nr = DRM_IOCTL_NR(cmd); - struct drm_file *file_priv = filp->private_data; - drm_ioctl_compat_t *fn = NULL; - int ret; - - if (nr < DRM_COMMAND_BASE) - return drm_compat_ioctl(filp, cmd, arg); - - if (nr >= DRM_COMMAND_BASE + ARRAY_SIZE(mga_compat_ioctls)) - return drm_ioctl(filp, cmd, arg); - - fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE].fn; - if (!fn) - return drm_ioctl(filp, cmd, arg); - - DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", - task_pid_nr(current), - (long)old_encode_dev(file_priv->minor->kdev->devt), - file_priv->authenticated, - mga_compat_ioctls[nr - DRM_COMMAND_BASE].name); - ret = (*fn) (filp, cmd, arg); - if (ret) - DRM_DEBUG("ret = %d\n", ret); - return ret; -} diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c deleted file mode 100644 index a7e6ffc80a78..000000000000 --- a/drivers/gpu/drm/mga/mga_irq.c +++ /dev/null @@ -1,169 +0,0 @@ -/* mga_irq.c -- IRQ handling for radeon -*- linux-c -*- - */ -/* - * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. - * - * The Weather Channel (TM) funded Tungsten Graphics to develop the - * initial release of the Radeon 8500 driver under the XFree86 license. - * This notice must be preserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell - * Eric Anholt - */ - -#include "mga_drv.h" - -u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe) -{ - const drm_mga_private_t *const dev_priv = - (drm_mga_private_t *) dev->dev_private; - - if (pipe != 0) - return 0; - - return atomic_read(&dev_priv->vbl_received); -} - - -irqreturn_t mga_driver_irq_handler(int irq, void *arg) -{ - struct drm_device *dev = (struct drm_device *) arg; - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - int status; - int handled = 0; - - status = MGA_READ(MGA_STATUS); - - /* VBLANK interrupt */ - if (status & MGA_VLINEPEN) { - MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR); - atomic_inc(&dev_priv->vbl_received); - drm_handle_vblank(dev, 0); - handled = 1; - } - - /* SOFTRAP interrupt */ - if (status & MGA_SOFTRAPEN) { - const u32 prim_start = MGA_READ(MGA_PRIMADDRESS); - const u32 prim_end = MGA_READ(MGA_PRIMEND); - - - MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR); - - /* In addition to clearing the interrupt-pending bit, we - * have to write to MGA_PRIMEND to re-start the DMA operation. - */ - if ((prim_start & ~0x03) != (prim_end & ~0x03)) - MGA_WRITE(MGA_PRIMEND, prim_end); - - atomic_inc(&dev_priv->last_fence_retired); - wake_up(&dev_priv->fence_queue); - handled = 1; - } - - if (handled) - return IRQ_HANDLED; - return IRQ_NONE; -} - -int mga_enable_vblank(struct drm_device *dev, unsigned int pipe) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - - if (pipe != 0) { - DRM_ERROR("tried to enable vblank on non-existent crtc %u\n", - pipe); - return 0; - } - - MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); - return 0; -} - - -void mga_disable_vblank(struct drm_device *dev, unsigned int pipe) -{ - if (pipe != 0) { - DRM_ERROR("tried to disable vblank on non-existent crtc %u\n", - pipe); - } - - /* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have - * a nice hardware counter that tracks the number of refreshes when - * the interrupt is disabled, and the kernel doesn't know the refresh - * rate to calculate an estimate. - */ - /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */ -} - -void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - unsigned int cur_fence; - - /* Assume that the user has missed the current sequence number - * by about a day rather than she wants to wait for years - * using fences. - */ - wait_event_timeout(dev_priv->fence_queue, - (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) - - *sequence) <= (1 << 23)), - msecs_to_jiffies(3000)); - - *sequence = cur_fence; -} - -void mga_driver_irq_preinstall(struct drm_device *dev) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - - /* Disable *all* interrupts */ - MGA_WRITE(MGA_IEN, 0); - /* Clear bits if they're already high */ - MGA_WRITE(MGA_ICLEAR, ~0); -} - -int mga_driver_irq_postinstall(struct drm_device *dev) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - - init_waitqueue_head(&dev_priv->fence_queue); - - /* Turn on soft trap interrupt. Vertical blank interrupts are enabled - * in mga_enable_vblank. - */ - MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN); - return 0; -} - -void mga_driver_irq_uninstall(struct drm_device *dev) -{ - drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - if (!dev_priv) - return; - - /* Disable *all* interrupts */ - MGA_WRITE(MGA_IEN, 0); - - dev->irq_enabled = false; -} diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c deleted file mode 100644 index 5b7247b58451..000000000000 --- a/drivers/gpu/drm/mga/mga_state.c +++ /dev/null @@ -1,1099 +0,0 @@ -/* mga_state.c -- State support for MGA G200/G400 -*- linux-c -*- - * Created: Thu Jan 27 02:53:43 2000 by jhartmann@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jeff Hartmann - * Keith Whitwell - * - * Rewritten by: - * Gareth Hughes - */ - -#include "mga_drv.h" - -/* ================================================================ - * DMA hardware state programming functions - */ - -static void mga_emit_clip_rect(drm_mga_private_t *dev_priv, - struct drm_clip_rect *box) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_context_regs_t *ctx = &sarea_priv->context_state; - unsigned int pitch = dev_priv->front_pitch; - DMA_LOCALS; - - BEGIN_DMA(2); - - /* Force reset of DWGCTL on G400 (eliminates clip disable bit). - */ - if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { - DMA_BLOCK(MGA_DWGCTL, ctx->dwgctl, - MGA_LEN + MGA_EXEC, 0x80000000, - MGA_DWGCTL, ctx->dwgctl, - MGA_LEN + MGA_EXEC, 0x80000000); - } - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_CXBNDRY, ((box->x2 - 1) << 16) | box->x1, - MGA_YTOP, box->y1 * pitch, MGA_YBOT, (box->y2 - 1) * pitch); - - ADVANCE_DMA(); -} - -static __inline__ void mga_g200_emit_context(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_context_regs_t *ctx = &sarea_priv->context_state; - DMA_LOCALS; - - BEGIN_DMA(3); - - DMA_BLOCK(MGA_DSTORG, ctx->dstorg, - MGA_MACCESS, ctx->maccess, - MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); - - DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, - MGA_FOGCOL, ctx->fogcolor, - MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); - - DMA_BLOCK(MGA_FCOL, ctx->fcol, - MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); - - ADVANCE_DMA(); -} - -static __inline__ void mga_g400_emit_context(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_context_regs_t *ctx = &sarea_priv->context_state; - DMA_LOCALS; - - BEGIN_DMA(4); - - DMA_BLOCK(MGA_DSTORG, ctx->dstorg, - MGA_MACCESS, ctx->maccess, - MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); - - DMA_BLOCK(MGA_ALPHACTRL, ctx->alphactrl, - MGA_FOGCOL, ctx->fogcolor, - MGA_WFLAG, ctx->wflag, MGA_ZORG, dev_priv->depth_offset); - - DMA_BLOCK(MGA_WFLAG1, ctx->wflag, - MGA_TDUALSTAGE0, ctx->tdualstage0, - MGA_TDUALSTAGE1, ctx->tdualstage1, MGA_FCOL, ctx->fcol); - - DMA_BLOCK(MGA_STENCIL, ctx->stencil, - MGA_STENCILCTL, ctx->stencilctl, - MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); - - ADVANCE_DMA(); -} - -static __inline__ void mga_g200_emit_tex0(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; - DMA_LOCALS; - - BEGIN_DMA(4); - - DMA_BLOCK(MGA_TEXCTL2, tex->texctl2, - MGA_TEXCTL, tex->texctl, - MGA_TEXFILTER, tex->texfilter, - MGA_TEXBORDERCOL, tex->texbordercol); - - DMA_BLOCK(MGA_TEXORG, tex->texorg, - MGA_TEXORG1, tex->texorg1, - MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); - - DMA_BLOCK(MGA_TEXORG4, tex->texorg4, - MGA_TEXWIDTH, tex->texwidth, - MGA_TEXHEIGHT, tex->texheight, MGA_WR24, tex->texwidth); - - DMA_BLOCK(MGA_WR34, tex->texheight, - MGA_TEXTRANS, 0x0000ffff, - MGA_TEXTRANSHIGH, 0x0000ffff, MGA_DMAPAD, 0x00000000); - - ADVANCE_DMA(); -} - -static __inline__ void mga_g400_emit_tex0(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0]; - DMA_LOCALS; - -/* printk("mga_g400_emit_tex0 %x %x %x\n", tex->texorg, */ -/* tex->texctl, tex->texctl2); */ - - BEGIN_DMA(6); - - DMA_BLOCK(MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC, - MGA_TEXCTL, tex->texctl, - MGA_TEXFILTER, tex->texfilter, - MGA_TEXBORDERCOL, tex->texbordercol); - - DMA_BLOCK(MGA_TEXORG, tex->texorg, - MGA_TEXORG1, tex->texorg1, - MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); - - DMA_BLOCK(MGA_TEXORG4, tex->texorg4, - MGA_TEXWIDTH, tex->texwidth, - MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000); - - DMA_BLOCK(MGA_WR57, 0x00000000, - MGA_WR53, 0x00000000, - MGA_WR61, 0x00000000, MGA_WR52, MGA_G400_WR_MAGIC); - - DMA_BLOCK(MGA_WR60, MGA_G400_WR_MAGIC, - MGA_WR54, tex->texwidth | MGA_G400_WR_MAGIC, - MGA_WR62, tex->texheight | MGA_G400_WR_MAGIC, - MGA_DMAPAD, 0x00000000); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_TEXTRANS, 0x0000ffff, MGA_TEXTRANSHIGH, 0x0000ffff); - - ADVANCE_DMA(); -} - -static __inline__ void mga_g400_emit_tex1(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1]; - DMA_LOCALS; - -/* printk("mga_g400_emit_tex1 %x %x %x\n", tex->texorg, */ -/* tex->texctl, tex->texctl2); */ - - BEGIN_DMA(5); - - DMA_BLOCK(MGA_TEXCTL2, (tex->texctl2 | - MGA_MAP1_ENABLE | - MGA_G400_TC2_MAGIC), - MGA_TEXCTL, tex->texctl, - MGA_TEXFILTER, tex->texfilter, - MGA_TEXBORDERCOL, tex->texbordercol); - - DMA_BLOCK(MGA_TEXORG, tex->texorg, - MGA_TEXORG1, tex->texorg1, - MGA_TEXORG2, tex->texorg2, MGA_TEXORG3, tex->texorg3); - - DMA_BLOCK(MGA_TEXORG4, tex->texorg4, - MGA_TEXWIDTH, tex->texwidth, - MGA_TEXHEIGHT, tex->texheight, MGA_WR49, 0x00000000); - - DMA_BLOCK(MGA_WR57, 0x00000000, - MGA_WR53, 0x00000000, - MGA_WR61, 0x00000000, - MGA_WR52, tex->texwidth | MGA_G400_WR_MAGIC); - - DMA_BLOCK(MGA_WR60, tex->texheight | MGA_G400_WR_MAGIC, - MGA_TEXTRANS, 0x0000ffff, - MGA_TEXTRANSHIGH, 0x0000ffff, - MGA_TEXCTL2, tex->texctl2 | MGA_G400_TC2_MAGIC); - - ADVANCE_DMA(); -} - -static __inline__ void mga_g200_emit_pipe(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int pipe = sarea_priv->warp_pipe; - DMA_LOCALS; - - BEGIN_DMA(3); - - DMA_BLOCK(MGA_WIADDR, MGA_WMODE_SUSPEND, - MGA_WVRTXSZ, 0x00000007, - MGA_WFLAG, 0x00000000, MGA_WR24, 0x00000000); - - DMA_BLOCK(MGA_WR25, 0x00000100, - MGA_WR34, 0x00000000, - MGA_WR42, 0x0000ffff, MGA_WR60, 0x0000ffff); - - /* Padding required due to hardware bug. - */ - DMA_BLOCK(MGA_DMAPAD, 0xffffffff, - MGA_DMAPAD, 0xffffffff, - MGA_DMAPAD, 0xffffffff, - MGA_WIADDR, (dev_priv->warp_pipe_phys[pipe] | - MGA_WMODE_START | dev_priv->wagp_enable)); - - ADVANCE_DMA(); -} - -static __inline__ void mga_g400_emit_pipe(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int pipe = sarea_priv->warp_pipe; - DMA_LOCALS; - -/* printk("mga_g400_emit_pipe %x\n", pipe); */ - - BEGIN_DMA(10); - - DMA_BLOCK(MGA_WIADDR2, MGA_WMODE_SUSPEND, - MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); - - if (pipe & MGA_T2) { - DMA_BLOCK(MGA_WVRTXSZ, 0x00001e09, - MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); - - DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, - MGA_WACCEPTSEQ, 0x00000000, - MGA_WACCEPTSEQ, 0x00000000, - MGA_WACCEPTSEQ, 0x1e000000); - } else { - if (dev_priv->warp_pipe & MGA_T2) { - /* Flush the WARP pipe */ - DMA_BLOCK(MGA_YDST, 0x00000000, - MGA_FXLEFT, 0x00000000, - MGA_FXRIGHT, 0x00000001, - MGA_DWGCTL, MGA_DWGCTL_FLUSH); - - DMA_BLOCK(MGA_LEN + MGA_EXEC, 0x00000001, - MGA_DWGSYNC, 0x00007000, - MGA_TEXCTL2, MGA_G400_TC2_MAGIC, - MGA_LEN + MGA_EXEC, 0x00000000); - - DMA_BLOCK(MGA_TEXCTL2, (MGA_DUALTEX | - MGA_G400_TC2_MAGIC), - MGA_LEN + MGA_EXEC, 0x00000000, - MGA_TEXCTL2, MGA_G400_TC2_MAGIC, - MGA_DMAPAD, 0x00000000); - } - - DMA_BLOCK(MGA_WVRTXSZ, 0x00001807, - MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, MGA_DMAPAD, 0x00000000); - - DMA_BLOCK(MGA_WACCEPTSEQ, 0x00000000, - MGA_WACCEPTSEQ, 0x00000000, - MGA_WACCEPTSEQ, 0x00000000, - MGA_WACCEPTSEQ, 0x18000000); - } - - DMA_BLOCK(MGA_WFLAG, 0x00000000, - MGA_WFLAG1, 0x00000000, - MGA_WR56, MGA_G400_WR56_MAGIC, MGA_DMAPAD, 0x00000000); - - DMA_BLOCK(MGA_WR49, 0x00000000, /* tex0 */ - MGA_WR57, 0x00000000, /* tex0 */ - MGA_WR53, 0x00000000, /* tex1 */ - MGA_WR61, 0x00000000); /* tex1 */ - - DMA_BLOCK(MGA_WR54, MGA_G400_WR_MAGIC, /* tex0 width */ - MGA_WR62, MGA_G400_WR_MAGIC, /* tex0 height */ - MGA_WR52, MGA_G400_WR_MAGIC, /* tex1 width */ - MGA_WR60, MGA_G400_WR_MAGIC); /* tex1 height */ - - /* Padding required due to hardware bug */ - DMA_BLOCK(MGA_DMAPAD, 0xffffffff, - MGA_DMAPAD, 0xffffffff, - MGA_DMAPAD, 0xffffffff, - MGA_WIADDR2, (dev_priv->warp_pipe_phys[pipe] | - MGA_WMODE_START | dev_priv->wagp_enable)); - - ADVANCE_DMA(); -} - -static void mga_g200_emit_state(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int dirty = sarea_priv->dirty; - - if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { - mga_g200_emit_pipe(dev_priv); - dev_priv->warp_pipe = sarea_priv->warp_pipe; - } - - if (dirty & MGA_UPLOAD_CONTEXT) { - mga_g200_emit_context(dev_priv); - sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; - } - - if (dirty & MGA_UPLOAD_TEX0) { - mga_g200_emit_tex0(dev_priv); - sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; - } -} - -static void mga_g400_emit_state(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int dirty = sarea_priv->dirty; - int multitex = sarea_priv->warp_pipe & MGA_T2; - - if (sarea_priv->warp_pipe != dev_priv->warp_pipe) { - mga_g400_emit_pipe(dev_priv); - dev_priv->warp_pipe = sarea_priv->warp_pipe; - } - - if (dirty & MGA_UPLOAD_CONTEXT) { - mga_g400_emit_context(dev_priv); - sarea_priv->dirty &= ~MGA_UPLOAD_CONTEXT; - } - - if (dirty & MGA_UPLOAD_TEX0) { - mga_g400_emit_tex0(dev_priv); - sarea_priv->dirty &= ~MGA_UPLOAD_TEX0; - } - - if ((dirty & MGA_UPLOAD_TEX1) && multitex) { - mga_g400_emit_tex1(dev_priv); - sarea_priv->dirty &= ~MGA_UPLOAD_TEX1; - } -} - -/* ================================================================ - * SAREA state verification - */ - -/* Disallow all write destinations except the front and backbuffer. - */ -static int mga_verify_context(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_context_regs_t *ctx = &sarea_priv->context_state; - - if (ctx->dstorg != dev_priv->front_offset && - ctx->dstorg != dev_priv->back_offset) { - DRM_ERROR("*** bad DSTORG: %x (front %x, back %x)\n\n", - ctx->dstorg, dev_priv->front_offset, - dev_priv->back_offset); - ctx->dstorg = 0; - return -EINVAL; - } - - return 0; -} - -/* Disallow texture reads from PCI space. - */ -static int mga_verify_tex(drm_mga_private_t *dev_priv, int unit) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit]; - unsigned int org; - - org = tex->texorg & (MGA_TEXORGMAP_MASK | MGA_TEXORGACC_MASK); - - if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) { - DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit); - tex->texorg = 0; - return -EINVAL; - } - - return 0; -} - -static int mga_verify_state(drm_mga_private_t *dev_priv) -{ - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int dirty = sarea_priv->dirty; - int ret = 0; - - if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; - - if (dirty & MGA_UPLOAD_CONTEXT) - ret |= mga_verify_context(dev_priv); - - if (dirty & MGA_UPLOAD_TEX0) - ret |= mga_verify_tex(dev_priv, 0); - - if (dev_priv->chipset >= MGA_CARD_TYPE_G400) { - if (dirty & MGA_UPLOAD_TEX1) - ret |= mga_verify_tex(dev_priv, 1); - - if (dirty & MGA_UPLOAD_PIPE) - ret |= (sarea_priv->warp_pipe > MGA_MAX_G400_PIPES); - } else { - if (dirty & MGA_UPLOAD_PIPE) - ret |= (sarea_priv->warp_pipe > MGA_MAX_G200_PIPES); - } - - return (ret == 0); -} - -static int mga_verify_iload(drm_mga_private_t *dev_priv, - unsigned int dstorg, unsigned int length) -{ - if (dstorg < dev_priv->texture_offset || - dstorg + length > (dev_priv->texture_offset + - dev_priv->texture_size)) { - DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg); - return -EINVAL; - } - - if (length & MGA_ILOAD_MASK) { - DRM_ERROR("*** bad iload length: 0x%x\n", - length & MGA_ILOAD_MASK); - return -EINVAL; - } - - return 0; -} - -static int mga_verify_blit(drm_mga_private_t *dev_priv, - unsigned int srcorg, unsigned int dstorg) -{ - if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) || - (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) { - DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg); - return -EINVAL; - } - return 0; -} - -/* ================================================================ - * - */ - -static void mga_dma_dispatch_clear(struct drm_device *dev, drm_mga_clear_t *clear) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_context_regs_t *ctx = &sarea_priv->context_state; - struct drm_clip_rect *pbox = sarea_priv->boxes; - int nbox = sarea_priv->nbox; - int i; - DMA_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_DMA(1); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); - - ADVANCE_DMA(); - - for (i = 0; i < nbox; i++) { - struct drm_clip_rect *box = &pbox[i]; - u32 height = box->y2 - box->y1; - - DRM_DEBUG(" from=%d,%d to=%d,%d\n", - box->x1, box->y1, box->x2, box->y2); - - if (clear->flags & MGA_FRONT) { - BEGIN_DMA(2); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_PLNWT, clear->color_mask, - MGA_YDSTLEN, (box->y1 << 16) | height, - MGA_FXBNDRY, (box->x2 << 16) | box->x1); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_FCOL, clear->clear_color, - MGA_DSTORG, dev_priv->front_offset, - MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); - - ADVANCE_DMA(); - } - - if (clear->flags & MGA_BACK) { - BEGIN_DMA(2); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_PLNWT, clear->color_mask, - MGA_YDSTLEN, (box->y1 << 16) | height, - MGA_FXBNDRY, (box->x2 << 16) | box->x1); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_FCOL, clear->clear_color, - MGA_DSTORG, dev_priv->back_offset, - MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); - - ADVANCE_DMA(); - } - - if (clear->flags & MGA_DEPTH) { - BEGIN_DMA(2); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_PLNWT, clear->depth_mask, - MGA_YDSTLEN, (box->y1 << 16) | height, - MGA_FXBNDRY, (box->x2 << 16) | box->x1); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_FCOL, clear->clear_depth, - MGA_DSTORG, dev_priv->depth_offset, - MGA_DWGCTL + MGA_EXEC, dev_priv->clear_cmd); - - ADVANCE_DMA(); - } - - } - - BEGIN_DMA(1); - - /* Force reset of DWGCTL */ - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_PLNWT, ctx->plnwt, MGA_DWGCTL, ctx->dwgctl); - - ADVANCE_DMA(); - - FLUSH_DMA(); -} - -static void mga_dma_dispatch_swap(struct drm_device *dev) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_context_regs_t *ctx = &sarea_priv->context_state; - struct drm_clip_rect *pbox = sarea_priv->boxes; - int nbox = sarea_priv->nbox; - int i; - DMA_LOCALS; - DRM_DEBUG("\n"); - - sarea_priv->last_frame.head = dev_priv->prim.tail; - sarea_priv->last_frame.wrap = dev_priv->prim.last_wrap; - - BEGIN_DMA(4 + nbox); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); - - DMA_BLOCK(MGA_DSTORG, dev_priv->front_offset, - MGA_MACCESS, dev_priv->maccess, - MGA_SRCORG, dev_priv->back_offset, - MGA_AR5, dev_priv->front_pitch); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_PLNWT, 0xffffffff, MGA_DWGCTL, MGA_DWGCTL_COPY); - - for (i = 0; i < nbox; i++) { - struct drm_clip_rect *box = &pbox[i]; - u32 height = box->y2 - box->y1; - u32 start = box->y1 * dev_priv->front_pitch; - - DRM_DEBUG(" from=%d,%d to=%d,%d\n", - box->x1, box->y1, box->x2, box->y2); - - DMA_BLOCK(MGA_AR0, start + box->x2 - 1, - MGA_AR3, start + box->x1, - MGA_FXBNDRY, ((box->x2 - 1) << 16) | box->x1, - MGA_YDSTLEN + MGA_EXEC, (box->y1 << 16) | height); - } - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_PLNWT, ctx->plnwt, - MGA_SRCORG, dev_priv->front_offset, MGA_DWGCTL, ctx->dwgctl); - - ADVANCE_DMA(); - - FLUSH_DMA(); - - DRM_DEBUG("... done.\n"); -} - -static void mga_dma_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_buf_priv_t *buf_priv = buf->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - u32 address = (u32) buf->bus_address; - u32 length = (u32) buf->used; - int i = 0; - DMA_LOCALS; - DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); - - if (buf->used) { - buf_priv->dispatched = 1; - - MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); - - do { - if (i < sarea_priv->nbox) { - mga_emit_clip_rect(dev_priv, - &sarea_priv->boxes[i]); - } - - BEGIN_DMA(1); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_SECADDRESS, (address | - MGA_DMA_VERTEX), - MGA_SECEND, ((address + length) | - dev_priv->dma_access)); - - ADVANCE_DMA(); - } while (++i < sarea_priv->nbox); - } - - if (buf_priv->discard) { - AGE_BUFFER(buf_priv); - buf->pending = 0; - buf->used = 0; - buf_priv->dispatched = 0; - - mga_freelist_put(dev, buf); - } - - FLUSH_DMA(); -} - -static void mga_dma_dispatch_indices(struct drm_device *dev, struct drm_buf *buf, - unsigned int start, unsigned int end) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_buf_priv_t *buf_priv = buf->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - u32 address = (u32) buf->bus_address; - int i = 0; - DMA_LOCALS; - DRM_DEBUG("buf=%d start=%d end=%d\n", buf->idx, start, end); - - if (start != end) { - buf_priv->dispatched = 1; - - MGA_EMIT_STATE(dev_priv, sarea_priv->dirty); - - do { - if (i < sarea_priv->nbox) { - mga_emit_clip_rect(dev_priv, - &sarea_priv->boxes[i]); - } - - BEGIN_DMA(1); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_SETUPADDRESS, address + start, - MGA_SETUPEND, ((address + end) | - dev_priv->dma_access)); - - ADVANCE_DMA(); - } while (++i < sarea_priv->nbox); - } - - if (buf_priv->discard) { - AGE_BUFFER(buf_priv); - buf->pending = 0; - buf->used = 0; - buf_priv->dispatched = 0; - - mga_freelist_put(dev, buf); - } - - FLUSH_DMA(); -} - -/* This copies a 64 byte aligned agp region to the frambuffer with a - * standard blit, the ioctl needs to do checking. - */ -static void mga_dma_dispatch_iload(struct drm_device *dev, struct drm_buf *buf, - unsigned int dstorg, unsigned int length) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_buf_priv_t *buf_priv = buf->dev_private; - drm_mga_context_regs_t *ctx = &dev_priv->sarea_priv->context_state; - u32 srcorg = - buf->bus_address | dev_priv->dma_access | MGA_SRCMAP_SYSMEM; - u32 y2; - DMA_LOCALS; - DRM_DEBUG("buf=%d used=%d\n", buf->idx, buf->used); - - y2 = length / 64; - - BEGIN_DMA(5); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); - - DMA_BLOCK(MGA_DSTORG, dstorg, - MGA_MACCESS, 0x00000000, MGA_SRCORG, srcorg, MGA_AR5, 64); - - DMA_BLOCK(MGA_PITCH, 64, - MGA_PLNWT, 0xffffffff, - MGA_DMAPAD, 0x00000000, MGA_DWGCTL, MGA_DWGCTL_COPY); - - DMA_BLOCK(MGA_AR0, 63, - MGA_AR3, 0, - MGA_FXBNDRY, (63 << 16) | 0, MGA_YDSTLEN + MGA_EXEC, y2); - - DMA_BLOCK(MGA_PLNWT, ctx->plnwt, - MGA_SRCORG, dev_priv->front_offset, - MGA_PITCH, dev_priv->front_pitch, MGA_DWGSYNC, 0x00007000); - - ADVANCE_DMA(); - - AGE_BUFFER(buf_priv); - - buf->pending = 0; - buf->used = 0; - buf_priv->dispatched = 0; - - mga_freelist_put(dev, buf); - - FLUSH_DMA(); -} - -static void mga_dma_dispatch_blit(struct drm_device *dev, drm_mga_blit_t *blit) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_context_regs_t *ctx = &sarea_priv->context_state; - struct drm_clip_rect *pbox = sarea_priv->boxes; - int nbox = sarea_priv->nbox; - u32 scandir = 0, i; - DMA_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_DMA(4 + nbox); - - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_DWGSYNC, 0x00007100, MGA_DWGSYNC, 0x00007000); - - DMA_BLOCK(MGA_DWGCTL, MGA_DWGCTL_COPY, - MGA_PLNWT, blit->planemask, - MGA_SRCORG, blit->srcorg, MGA_DSTORG, blit->dstorg); - - DMA_BLOCK(MGA_SGN, scandir, - MGA_MACCESS, dev_priv->maccess, - MGA_AR5, blit->ydir * blit->src_pitch, - MGA_PITCH, blit->dst_pitch); - - for (i = 0; i < nbox; i++) { - int srcx = pbox[i].x1 + blit->delta_sx; - int srcy = pbox[i].y1 + blit->delta_sy; - int dstx = pbox[i].x1 + blit->delta_dx; - int dsty = pbox[i].y1 + blit->delta_dy; - int h = pbox[i].y2 - pbox[i].y1; - int w = pbox[i].x2 - pbox[i].x1 - 1; - int start; - - if (blit->ydir == -1) - srcy = blit->height - srcy - 1; - - start = srcy * blit->src_pitch + srcx; - - DMA_BLOCK(MGA_AR0, start + w, - MGA_AR3, start, - MGA_FXBNDRY, ((dstx + w) << 16) | (dstx & 0xffff), - MGA_YDSTLEN + MGA_EXEC, (dsty << 16) | h); - } - - /* Do something to flush AGP? - */ - - /* Force reset of DWGCTL */ - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_PLNWT, ctx->plnwt, - MGA_PITCH, dev_priv->front_pitch, MGA_DWGCTL, ctx->dwgctl); - - ADVANCE_DMA(); -} - -/* ================================================================ - * - */ - -static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_clear_t *clear = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; - - WRAP_TEST_WITH_RETURN(dev_priv); - - mga_dma_dispatch_clear(dev, clear); - - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; - - return 0; -} - -static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; - - WRAP_TEST_WITH_RETURN(dev_priv); - - mga_dma_dispatch_swap(dev); - - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; - - return 0; -} - -static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_mga_buf_priv_t *buf_priv; - drm_mga_vertex_t *vertex = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (vertex->idx < 0 || vertex->idx > dma->buf_count) - return -EINVAL; - buf = dma->buflist[vertex->idx]; - buf_priv = buf->dev_private; - - buf->used = vertex->used; - buf_priv->discard = vertex->discard; - - if (!mga_verify_state(dev_priv)) { - if (vertex->discard) { - if (buf_priv->dispatched == 1) - AGE_BUFFER(buf_priv); - buf_priv->dispatched = 0; - mga_freelist_put(dev, buf); - } - return -EINVAL; - } - - WRAP_TEST_WITH_RETURN(dev_priv); - - mga_dma_dispatch_vertex(dev, buf); - - return 0; -} - -static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_mga_buf_priv_t *buf_priv; - drm_mga_indices_t *indices = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (indices->idx < 0 || indices->idx > dma->buf_count) - return -EINVAL; - - buf = dma->buflist[indices->idx]; - buf_priv = buf->dev_private; - - buf_priv->discard = indices->discard; - - if (!mga_verify_state(dev_priv)) { - if (indices->discard) { - if (buf_priv->dispatched == 1) - AGE_BUFFER(buf_priv); - buf_priv->dispatched = 0; - mga_freelist_put(dev, buf); - } - return -EINVAL; - } - - WRAP_TEST_WITH_RETURN(dev_priv); - - mga_dma_dispatch_indices(dev, buf, indices->start, indices->end); - - return 0; -} - -static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - drm_mga_private_t *dev_priv = dev->dev_private; - struct drm_buf *buf; - drm_mga_iload_t *iload = data; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - -#if 0 - if (mga_do_wait_for_idle(dev_priv) < 0) { - if (MGA_DMA_DEBUG) - DRM_INFO("-EBUSY\n"); - return -EBUSY; - } -#endif - if (iload->idx < 0 || iload->idx > dma->buf_count) - return -EINVAL; - - buf = dma->buflist[iload->idx]; - - if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) { - mga_freelist_put(dev, buf); - return -EINVAL; - } - - WRAP_TEST_WITH_RETURN(dev_priv); - - mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length); - - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; - - return 0; -} - -static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_blit_t *blit = data; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; - - if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg)) - return -EINVAL; - - WRAP_TEST_WITH_RETURN(dev_priv); - - mga_dma_dispatch_blit(dev, blit); - - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= MGA_UPLOAD_CONTEXT; - - return 0; -} - -int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_getparam_t *param = data; - struct pci_dev *pdev = to_pci_dev(dev->dev); - int value; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - DRM_DEBUG("pid=%d\n", task_pid_nr(current)); - - switch (param->param) { - case MGA_PARAM_IRQ_NR: - value = pdev->irq; - break; - case MGA_PARAM_CARD_TYPE: - value = dev_priv->chipset; - break; - default: - return -EINVAL; - } - - if (copy_to_user(param->value, &value, sizeof(int))) { - DRM_ERROR("copy_to_user\n"); - return -EFAULT; - } - - return 0; -} - -static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - u32 *fence = data; - DMA_LOCALS; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - DRM_DEBUG("pid=%d\n", task_pid_nr(current)); - - /* I would normal do this assignment in the declaration of fence, - * but dev_priv may be NULL. - */ - - *fence = dev_priv->next_fence_to_post; - dev_priv->next_fence_to_post++; - - BEGIN_DMA(1); - DMA_BLOCK(MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, - MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000); - ADVANCE_DMA(); - - return 0; -} - -static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file * -file_priv) -{ - drm_mga_private_t *dev_priv = dev->dev_private; - u32 *fence = data; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - DRM_DEBUG("pid=%d\n", task_pid_nr(current)); - - mga_driver_fence_wait(dev, fence); - return 0; -} - -const struct drm_ioctl_desc mga_ioctls[] = { - DRM_IOCTL_DEF_DRV(MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(MGA_FLUSH, mga_dma_flush, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_RESET, mga_dma_reset, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_SWAP, mga_dma_swap, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_CLEAR, mga_dma_clear, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_VERTEX, mga_dma_vertex, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_INDICES, mga_dma_indices, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_ILOAD, mga_dma_iload, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_BLIT, mga_dma_blit, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_GETPARAM, mga_getparam, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_SET_FENCE, mga_set_fence, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH), - DRM_IOCTL_DEF_DRV(MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), -}; - -int mga_max_ioctl = ARRAY_SIZE(mga_ioctls); diff --git a/drivers/gpu/drm/mga/mga_warp.c b/drivers/gpu/drm/mga/mga_warp.c deleted file mode 100644 index b5ef1d2c8b1c..000000000000 --- a/drivers/gpu/drm/mga/mga_warp.c +++ /dev/null @@ -1,167 +0,0 @@ -/* mga_warp.c -- Matrox G200/G400 WARP engine management -*- linux-c -*- - * Created: Thu Jan 11 21:29:32 2001 by gareth@valinux.com - * - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Gareth Hughes - */ - -#include -#include -#include -#include - -#include "mga_drv.h" - -#define FIRMWARE_G200 "matrox/g200_warp.fw" -#define FIRMWARE_G400 "matrox/g400_warp.fw" - -MODULE_FIRMWARE(FIRMWARE_G200); -MODULE_FIRMWARE(FIRMWARE_G400); - -#define MGA_WARP_CODE_ALIGN 256 /* in bytes */ - -#define WARP_UCODE_SIZE(size) ALIGN(size, MGA_WARP_CODE_ALIGN) - -int mga_warp_install_microcode(drm_mga_private_t *dev_priv) -{ - unsigned char *vcbase = dev_priv->warp->handle; - unsigned long pcbase = dev_priv->warp->offset; - const char *firmware_name; - struct platform_device *pdev; - const struct firmware *fw = NULL; - const struct ihex_binrec *rec; - unsigned int size; - int n_pipes, where; - int rc = 0; - - switch (dev_priv->chipset) { - case MGA_CARD_TYPE_G400: - case MGA_CARD_TYPE_G550: - firmware_name = FIRMWARE_G400; - n_pipes = MGA_MAX_G400_PIPES; - break; - case MGA_CARD_TYPE_G200: - firmware_name = FIRMWARE_G200; - n_pipes = MGA_MAX_G200_PIPES; - break; - default: - return -EINVAL; - } - - pdev = platform_device_register_simple("mga_warp", 0, NULL, 0); - if (IS_ERR(pdev)) { - DRM_ERROR("mga: Failed to register microcode\n"); - return PTR_ERR(pdev); - } - rc = request_ihex_firmware(&fw, firmware_name, &pdev->dev); - platform_device_unregister(pdev); - if (rc) { - DRM_ERROR("mga: Failed to load microcode \"%s\"\n", - firmware_name); - return rc; - } - - size = 0; - where = 0; - for (rec = (const struct ihex_binrec *)fw->data; - rec; - rec = ihex_next_binrec(rec)) { - size += WARP_UCODE_SIZE(be16_to_cpu(rec->len)); - where++; - } - - if (where != n_pipes) { - DRM_ERROR("mga: Invalid microcode \"%s\"\n", firmware_name); - rc = -EINVAL; - goto out; - } - size = PAGE_ALIGN(size); - DRM_DEBUG("MGA ucode size = %d bytes\n", size); - if (size > dev_priv->warp->size) { - DRM_ERROR("microcode too large! (%u > %lu)\n", - size, dev_priv->warp->size); - rc = -ENOMEM; - goto out; - } - - memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys)); - - where = 0; - for (rec = (const struct ihex_binrec *)fw->data; - rec; - rec = ihex_next_binrec(rec)) { - unsigned int src_size, dst_size; - - DRM_DEBUG(" pcbase = 0x%08lx vcbase = %p\n", pcbase, vcbase); - dev_priv->warp_pipe_phys[where] = pcbase; - src_size = be16_to_cpu(rec->len); - dst_size = WARP_UCODE_SIZE(src_size); - memcpy(vcbase, rec->data, src_size); - pcbase += dst_size; - vcbase += dst_size; - where++; - } - -out: - release_firmware(fw); - return rc; -} - -#define WMISC_EXPECTED (MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE) - -int mga_warp_init(drm_mga_private_t *dev_priv) -{ - u32 wmisc; - - /* FIXME: Get rid of these damned magic numbers... - */ - switch (dev_priv->chipset) { - case MGA_CARD_TYPE_G400: - case MGA_CARD_TYPE_G550: - MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND); - MGA_WRITE(MGA_WGETMSB, 0x00000E00); - MGA_WRITE(MGA_WVRTXSZ, 0x00001807); - MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000); - break; - case MGA_CARD_TYPE_G200: - MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND); - MGA_WRITE(MGA_WGETMSB, 0x1606); - MGA_WRITE(MGA_WVRTXSZ, 7); - break; - default: - return -EINVAL; - } - - MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE | - MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE)); - wmisc = MGA_READ(MGA_WMISC); - if (wmisc != WMISC_EXPECTED) { - DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n", - wmisc, WMISC_EXPECTED); - return -EINVAL; - } - - return 0; -} diff --git a/include/uapi/drm/mga_drm.h b/include/uapi/drm/mga_drm.h deleted file mode 100644 index bb31567e66c0..000000000000 --- a/include/uapi/drm/mga_drm.h +++ /dev/null @@ -1,429 +0,0 @@ -/* mga_drm.h -- Public header for the Matrox g200/g400 driver -*- linux-c -*- - * Created: Tue Jan 25 01:50:01 1999 by jhartmann@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Jeff Hartmann - * Keith Whitwell - * - * Rewritten by: - * Gareth Hughes - */ - -#ifndef __MGA_DRM_H__ -#define __MGA_DRM_H__ - -#include "drm.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -/* WARNING: If you change any of these defines, make sure to change the - * defines in the Xserver file (mga_sarea.h) - */ - -#ifndef __MGA_SAREA_DEFINES__ -#define __MGA_SAREA_DEFINES__ - -/* WARP pipe flags - */ -#define MGA_F 0x1 /* fog */ -#define MGA_A 0x2 /* alpha */ -#define MGA_S 0x4 /* specular */ -#define MGA_T2 0x8 /* multitexture */ - -#define MGA_WARP_TGZ 0 -#define MGA_WARP_TGZF (MGA_F) -#define MGA_WARP_TGZA (MGA_A) -#define MGA_WARP_TGZAF (MGA_F|MGA_A) -#define MGA_WARP_TGZS (MGA_S) -#define MGA_WARP_TGZSF (MGA_S|MGA_F) -#define MGA_WARP_TGZSA (MGA_S|MGA_A) -#define MGA_WARP_TGZSAF (MGA_S|MGA_F|MGA_A) -#define MGA_WARP_T2GZ (MGA_T2) -#define MGA_WARP_T2GZF (MGA_T2|MGA_F) -#define MGA_WARP_T2GZA (MGA_T2|MGA_A) -#define MGA_WARP_T2GZAF (MGA_T2|MGA_A|MGA_F) -#define MGA_WARP_T2GZS (MGA_T2|MGA_S) -#define MGA_WARP_T2GZSF (MGA_T2|MGA_S|MGA_F) -#define MGA_WARP_T2GZSA (MGA_T2|MGA_S|MGA_A) -#define MGA_WARP_T2GZSAF (MGA_T2|MGA_S|MGA_F|MGA_A) - -#define MGA_MAX_G200_PIPES 8 /* no multitex */ -#define MGA_MAX_G400_PIPES 16 -#define MGA_MAX_WARP_PIPES MGA_MAX_G400_PIPES -#define MGA_WARP_UCODE_SIZE 32768 /* in bytes */ - -#define MGA_CARD_TYPE_G200 1 -#define MGA_CARD_TYPE_G400 2 -#define MGA_CARD_TYPE_G450 3 /* not currently used */ -#define MGA_CARD_TYPE_G550 4 - -#define MGA_FRONT 0x1 -#define MGA_BACK 0x2 -#define MGA_DEPTH 0x4 - -/* What needs to be changed for the current vertex dma buffer? - */ -#define MGA_UPLOAD_CONTEXT 0x1 -#define MGA_UPLOAD_TEX0 0x2 -#define MGA_UPLOAD_TEX1 0x4 -#define MGA_UPLOAD_PIPE 0x8 -#define MGA_UPLOAD_TEX0IMAGE 0x10 /* handled client-side */ -#define MGA_UPLOAD_TEX1IMAGE 0x20 /* handled client-side */ -#define MGA_UPLOAD_2D 0x40 -#define MGA_WAIT_AGE 0x80 /* handled client-side */ -#define MGA_UPLOAD_CLIPRECTS 0x100 /* handled client-side */ -#if 0 -#define MGA_DMA_FLUSH 0x200 /* set when someone gets the lock - quiescent */ -#endif - -/* 32 buffers of 64k each, total 2 meg. - */ -#define MGA_BUFFER_SIZE (1 << 16) -#define MGA_NUM_BUFFERS 128 - -/* Keep these small for testing. - */ -#define MGA_NR_SAREA_CLIPRECTS 8 - -/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 - * regions, subject to a minimum region size of (1<<16) == 64k. - * - * Clients may subdivide regions internally, but when sharing between - * clients, the region size is the minimum granularity. - */ - -#define MGA_CARD_HEAP 0 -#define MGA_AGP_HEAP 1 -#define MGA_NR_TEX_HEAPS 2 -#define MGA_NR_TEX_REGIONS 16 -#define MGA_LOG_MIN_TEX_REGION_SIZE 16 - -#define DRM_MGA_IDLE_RETRY 2048 - -#endif /* __MGA_SAREA_DEFINES__ */ - -/* Setup registers for 3D context - */ -typedef struct { - unsigned int dstorg; - unsigned int maccess; - unsigned int plnwt; - unsigned int dwgctl; - unsigned int alphactrl; - unsigned int fogcolor; - unsigned int wflag; - unsigned int tdualstage0; - unsigned int tdualstage1; - unsigned int fcol; - unsigned int stencil; - unsigned int stencilctl; -} drm_mga_context_regs_t; - -/* Setup registers for 2D, X server - */ -typedef struct { - unsigned int pitch; -} drm_mga_server_regs_t; - -/* Setup registers for each texture unit - */ -typedef struct { - unsigned int texctl; - unsigned int texctl2; - unsigned int texfilter; - unsigned int texbordercol; - unsigned int texorg; - unsigned int texwidth; - unsigned int texheight; - unsigned int texorg1; - unsigned int texorg2; - unsigned int texorg3; - unsigned int texorg4; -} drm_mga_texture_regs_t; - -/* General aging mechanism - */ -typedef struct { - unsigned int head; /* Position of head pointer */ - unsigned int wrap; /* Primary DMA wrap count */ -} drm_mga_age_t; - -typedef struct _drm_mga_sarea { - /* The channel for communication of state information to the kernel - * on firing a vertex dma buffer. - */ - drm_mga_context_regs_t context_state; - drm_mga_server_regs_t server_state; - drm_mga_texture_regs_t tex_state[2]; - unsigned int warp_pipe; - unsigned int dirty; - unsigned int vertsize; - - /* The current cliprects, or a subset thereof. - */ - struct drm_clip_rect boxes[MGA_NR_SAREA_CLIPRECTS]; - unsigned int nbox; - - /* Information about the most recently used 3d drawable. The - * client fills in the req_* fields, the server fills in the - * exported_ fields and puts the cliprects into boxes, above. - * - * The client clears the exported_drawable field before - * clobbering the boxes data. - */ - unsigned int req_drawable; /* the X drawable id */ - unsigned int req_draw_buffer; /* MGA_FRONT or MGA_BACK */ - - unsigned int exported_drawable; - unsigned int exported_index; - unsigned int exported_stamp; - unsigned int exported_buffers; - unsigned int exported_nfront; - unsigned int exported_nback; - int exported_back_x, exported_front_x, exported_w; - int exported_back_y, exported_front_y, exported_h; - struct drm_clip_rect exported_boxes[MGA_NR_SAREA_CLIPRECTS]; - - /* Counters for aging textures and for client-side throttling. - */ - unsigned int status[4]; - unsigned int last_wrap; - - drm_mga_age_t last_frame; - unsigned int last_enqueue; /* last time a buffer was enqueued */ - unsigned int last_dispatch; /* age of the most recently dispatched buffer */ - unsigned int last_quiescent; /* */ - - /* LRU lists for texture memory in agp space and on the card. - */ - struct drm_tex_region texList[MGA_NR_TEX_HEAPS][MGA_NR_TEX_REGIONS + 1]; - unsigned int texAge[MGA_NR_TEX_HEAPS]; - - /* Mechanism to validate card state. - */ - int ctxOwner; -} drm_mga_sarea_t; - -/* MGA specific ioctls - * The device specific ioctl range is 0x40 to 0x79. - */ -#define DRM_MGA_INIT 0x00 -#define DRM_MGA_FLUSH 0x01 -#define DRM_MGA_RESET 0x02 -#define DRM_MGA_SWAP 0x03 -#define DRM_MGA_CLEAR 0x04 -#define DRM_MGA_VERTEX 0x05 -#define DRM_MGA_INDICES 0x06 -#define DRM_MGA_ILOAD 0x07 -#define DRM_MGA_BLIT 0x08 -#define DRM_MGA_GETPARAM 0x09 - -/* 3.2: - * ioctls for operating on fences. - */ -#define DRM_MGA_SET_FENCE 0x0a -#define DRM_MGA_WAIT_FENCE 0x0b -#define DRM_MGA_DMA_BOOTSTRAP 0x0c - -#define DRM_IOCTL_MGA_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INIT, drm_mga_init_t) -#define DRM_IOCTL_MGA_FLUSH DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_FLUSH, struct drm_lock) -#define DRM_IOCTL_MGA_RESET DRM_IO( DRM_COMMAND_BASE + DRM_MGA_RESET) -#define DRM_IOCTL_MGA_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_MGA_SWAP) -#define DRM_IOCTL_MGA_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_CLEAR, drm_mga_clear_t) -#define DRM_IOCTL_MGA_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_VERTEX, drm_mga_vertex_t) -#define DRM_IOCTL_MGA_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_INDICES, drm_mga_indices_t) -#define DRM_IOCTL_MGA_ILOAD DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_ILOAD, drm_mga_iload_t) -#define DRM_IOCTL_MGA_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_BLIT, drm_mga_blit_t) -#define DRM_IOCTL_MGA_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_GETPARAM, drm_mga_getparam_t) -#define DRM_IOCTL_MGA_SET_FENCE DRM_IOW( DRM_COMMAND_BASE + DRM_MGA_SET_FENCE, __u32) -#define DRM_IOCTL_MGA_WAIT_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_WAIT_FENCE, __u32) -#define DRM_IOCTL_MGA_DMA_BOOTSTRAP DRM_IOWR(DRM_COMMAND_BASE + DRM_MGA_DMA_BOOTSTRAP, drm_mga_dma_bootstrap_t) - -typedef struct _drm_mga_warp_index { - int installed; - unsigned long phys_addr; - int size; -} drm_mga_warp_index_t; - -typedef struct drm_mga_init { - enum { - MGA_INIT_DMA = 0x01, - MGA_CLEANUP_DMA = 0x02 - } func; - - unsigned long sarea_priv_offset; - - __struct_group(/* no tag */, always32bit, /* no attrs */, - int chipset; - int sgram; - - unsigned int maccess; - - unsigned int fb_cpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - - unsigned int depth_cpp; - unsigned int depth_offset, depth_pitch; - - unsigned int texture_offset[MGA_NR_TEX_HEAPS]; - unsigned int texture_size[MGA_NR_TEX_HEAPS]; - ); - - unsigned long fb_offset; - unsigned long mmio_offset; - unsigned long status_offset; - unsigned long warp_offset; - unsigned long primary_offset; - unsigned long buffers_offset; -} drm_mga_init_t; - -typedef struct drm_mga_dma_bootstrap { - /** - * \name AGP texture region - * - * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, these fields will - * be filled in with the actual AGP texture settings. - * - * \warning - * If these fields are non-zero, but dma_mga_dma_bootstrap::agp_mode - * is zero, it means that PCI memory (most likely through the use of - * an IOMMU) is being used for "AGP" textures. - */ - /*@{ */ - unsigned long texture_handle; /**< Handle used to map AGP textures. */ - __u32 texture_size; /**< Size of the AGP texture region. */ - /*@} */ - - /** - * Requested size of the primary DMA region. - * - * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be - * filled in with the actual AGP mode. If AGP was not available - */ - __u32 primary_size; - - /** - * Requested number of secondary DMA buffers. - * - * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be - * filled in with the actual number of secondary DMA buffers - * allocated. Particularly when PCI DMA is used, this may be - * (subtantially) less than the number requested. - */ - __u32 secondary_bin_count; - - /** - * Requested size of each secondary DMA buffer. - * - * While the kernel \b is free to reduce - * dma_mga_dma_bootstrap::secondary_bin_count, it is \b not allowed - * to reduce dma_mga_dma_bootstrap::secondary_bin_size. - */ - __u32 secondary_bin_size; - - /** - * Bit-wise mask of AGPSTAT2_* values. Currently only \c AGPSTAT2_1X, - * \c AGPSTAT2_2X, and \c AGPSTAT2_4X are supported. If this value is - * zero, it means that PCI DMA should be used, even if AGP is - * possible. - * - * On return from the DRM_MGA_DMA_BOOTSTRAP ioctl, this field will be - * filled in with the actual AGP mode. If AGP was not available - * (i.e., PCI DMA was used), this value will be zero. - */ - __u32 agp_mode; - - /** - * Desired AGP GART size, measured in megabytes. - */ - __u8 agp_size; -} drm_mga_dma_bootstrap_t; - -typedef struct drm_mga_clear { - unsigned int flags; - unsigned int clear_color; - unsigned int clear_depth; - unsigned int color_mask; - unsigned int depth_mask; -} drm_mga_clear_t; - -typedef struct drm_mga_vertex { - int idx; /* buffer to queue */ - int used; /* bytes in use */ - int discard; /* client finished with buffer? */ -} drm_mga_vertex_t; - -typedef struct drm_mga_indices { - int idx; /* buffer to queue */ - unsigned int start; - unsigned int end; - int discard; /* client finished with buffer? */ -} drm_mga_indices_t; - -typedef struct drm_mga_iload { - int idx; - unsigned int dstorg; - unsigned int length; -} drm_mga_iload_t; - -typedef struct _drm_mga_blit { - unsigned int planemask; - unsigned int srcorg; - unsigned int dstorg; - int src_pitch, dst_pitch; - int delta_sx, delta_sy; - int delta_dx, delta_dy; - int height, ydir; /* flip image vertically */ - int source_pitch, dest_pitch; -} drm_mga_blit_t; - -/* 3.1: An ioctl to get parameters that aren't available to the 3d - * client any other way. - */ -#define MGA_PARAM_IRQ_NR 1 - -/* 3.2: Query the actual card type. The DDX only distinguishes between - * G200 chips and non-G200 chips, which it calls G400. It turns out that - * there are some very sublte differences between the G4x0 chips and the G550 - * chips. Using this parameter query, a client-side driver can detect the - * difference between a G4x0 and a G550. - */ -#define MGA_PARAM_CARD_TYPE 2 - -typedef struct drm_mga_getparam { - int param; - void __user *value; -} drm_mga_getparam_t; - -#if defined(__cplusplus) -} -#endif - -#endif -- cgit v1.2.3 From 28483b8666bfe7d0ec34cfc492d77e64f97f6de1 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Sat, 3 Dec 2022 18:22:54 +0800 Subject: drm: Remove the obsolete driver-r128 Commit 399516ab0fee ("MAINTAINERS: Add a bunch of legacy (UMS) DRM drivers") marked r128 driver obsolete 7 years ago. And the mesa UMD of this drm driver already in deprecated list in the link: https://docs.mesa3d.org/systems.html ATI Rage 128->drivers/gpu/drm/r128 It's time to remove this driver. Signed-off-by: Cai Huoqing Acked-by: Daniel Vetter Acked-by: Dave Airlie Acked-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20221203102502.3185-4-cai.huoqing@linux.dev --- drivers/gpu/drm/Kconfig | 9 - drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/r128/Makefile | 10 - drivers/gpu/drm/r128/ati_pcigart.c | 228 ----- drivers/gpu/drm/r128/ati_pcigart.h | 31 - drivers/gpu/drm/r128/r128_cce.c | 944 --------------------- drivers/gpu/drm/r128/r128_drv.c | 116 --- drivers/gpu/drm/r128/r128_drv.h | 544 ------------ drivers/gpu/drm/r128/r128_ioc32.c | 199 ----- drivers/gpu/drm/r128/r128_irq.c | 118 --- drivers/gpu/drm/r128/r128_state.c | 1641 ------------------------------------ include/uapi/drm/r128_drm.h | 336 -------- 12 files changed, 4177 deletions(-) delete mode 100644 drivers/gpu/drm/r128/Makefile delete mode 100644 drivers/gpu/drm/r128/ati_pcigart.c delete mode 100644 drivers/gpu/drm/r128/ati_pcigart.h delete mode 100644 drivers/gpu/drm/r128/r128_cce.c delete mode 100644 drivers/gpu/drm/r128/r128_drv.c delete mode 100644 drivers/gpu/drm/r128/r128_drv.h delete mode 100644 drivers/gpu/drm/r128/r128_ioc32.c delete mode 100644 drivers/gpu/drm/r128/r128_irq.c delete mode 100644 drivers/gpu/drm/r128/r128_state.c delete mode 100644 include/uapi/drm/r128_drm.h (limited to 'include') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 3aba47a790c3..d54bb7795330 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -405,15 +405,6 @@ config DRM_TDFX Choose this option if you have a 3dfx Banshee or Voodoo3 (or later), graphics card. If M is selected, the module will be called tdfx. -config DRM_R128 - tristate "ATI Rage 128" - depends on DRM && PCI - select FW_LOADER - help - Choose this option if you have an ATI Rage 128 graphics card. If M - is selected, the module will be called r128. AGP support for - this card is strongly suggested (unless you have a PCI version). - config DRM_SIS tristate "SiS video cards" depends on DRM && AGP diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 306f1f8fd830..76f8d567502a 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -134,7 +134,6 @@ obj-y += display/ obj-$(CONFIG_DRM_TTM) += ttm/ obj-$(CONFIG_DRM_SCHED) += scheduler/ obj-$(CONFIG_DRM_TDFX) += tdfx/ -obj-$(CONFIG_DRM_R128) += r128/ obj-$(CONFIG_DRM_RADEON)+= radeon/ obj-$(CONFIG_DRM_AMDGPU)+= amd/amdgpu/ obj-$(CONFIG_DRM_I915) += i915/ diff --git a/drivers/gpu/drm/r128/Makefile b/drivers/gpu/drm/r128/Makefile deleted file mode 100644 index c07a069533ef..000000000000 --- a/drivers/gpu/drm/r128/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the drm device driver. This driver provides support for the -# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. - -r128-y := r128_drv.o r128_cce.o r128_state.o r128_irq.o ati_pcigart.o - -r128-$(CONFIG_COMPAT) += r128_ioc32.o - -obj-$(CONFIG_DRM_R128) += r128.o diff --git a/drivers/gpu/drm/r128/ati_pcigart.c b/drivers/gpu/drm/r128/ati_pcigart.c deleted file mode 100644 index dde0501aea68..000000000000 --- a/drivers/gpu/drm/r128/ati_pcigart.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * \file ati_pcigart.c - * ATI PCI GART support - * - * \author Gareth Hughes - */ - -/* - * Created: Wed Dec 13 21:52:19 2000 by gareth@valinux.com - * - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include - -#include -#include -#include - -#include "ati_pcigart.h" - -# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ - -static int drm_ati_alloc_pcigart_table(struct drm_device *dev, - struct drm_ati_pcigart_info *gart_info) -{ - drm_dma_handle_t *dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); - - if (!dmah) - return -ENOMEM; - - dmah->size = gart_info->table_size; - dmah->vaddr = dma_alloc_coherent(dev->dev, - dmah->size, - &dmah->busaddr, - GFP_KERNEL); - - if (!dmah->vaddr) { - kfree(dmah); - return -ENOMEM; - } - - gart_info->table_handle = dmah; - return 0; -} - -static void drm_ati_free_pcigart_table(struct drm_device *dev, - struct drm_ati_pcigart_info *gart_info) -{ - drm_dma_handle_t *dmah = gart_info->table_handle; - - dma_free_coherent(dev->dev, dmah->size, dmah->vaddr, dmah->busaddr); - kfree(dmah); - - gart_info->table_handle = NULL; -} - -int drm_ati_pcigart_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) -{ - struct drm_sg_mem *entry = dev->sg; - struct pci_dev *pdev = to_pci_dev(dev->dev); - unsigned long pages; - int i; - int max_pages; - - /* we need to support large memory configurations */ - if (!entry) { - DRM_ERROR("no scatter/gather memory!\n"); - return 0; - } - - if (gart_info->bus_addr) { - - max_pages = (gart_info->table_size / sizeof(u32)); - pages = (entry->pages <= max_pages) - ? entry->pages : max_pages; - - for (i = 0; i < pages; i++) { - if (!entry->busaddr[i]) - break; - dma_unmap_page(&pdev->dev, entry->busaddr[i], - PAGE_SIZE, DMA_BIDIRECTIONAL); - } - - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) - gart_info->bus_addr = 0; - } - - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN && - gart_info->table_handle) { - drm_ati_free_pcigart_table(dev, gart_info); - } - - return 1; -} - -int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) -{ - struct drm_local_map *map = &gart_info->mapping; - struct drm_sg_mem *entry = dev->sg; - struct pci_dev *pdev = to_pci_dev(dev->dev); - void *address = NULL; - unsigned long pages; - u32 *pci_gart = NULL, page_base, gart_idx; - dma_addr_t bus_address = 0; - int i, j, ret = -ENOMEM; - int max_ati_pages, max_real_pages; - - if (!entry) { - DRM_ERROR("no scatter/gather memory!\n"); - goto done; - } - - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { - DRM_DEBUG("PCI: no table in VRAM: using normal RAM\n"); - - if (dma_set_mask(&pdev->dev, gart_info->table_mask)) { - DRM_ERROR("fail to set dma mask to 0x%Lx\n", - (unsigned long long)gart_info->table_mask); - ret = -EFAULT; - goto done; - } - - ret = drm_ati_alloc_pcigart_table(dev, gart_info); - if (ret) { - DRM_ERROR("cannot allocate PCI GART page!\n"); - goto done; - } - - pci_gart = gart_info->table_handle->vaddr; - address = gart_info->table_handle->vaddr; - bus_address = gart_info->table_handle->busaddr; - } else { - address = gart_info->addr; - bus_address = gart_info->bus_addr; - DRM_DEBUG("PCI: Gart Table: VRAM %08LX mapped at %08lX\n", - (unsigned long long)bus_address, - (unsigned long)address); - } - - - max_ati_pages = (gart_info->table_size / sizeof(u32)); - max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); - pages = (entry->pages <= max_real_pages) - ? entry->pages : max_real_pages; - - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) { - memset(pci_gart, 0, max_ati_pages * sizeof(u32)); - } else { - memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u32)); - } - - gart_idx = 0; - for (i = 0; i < pages; i++) { - /* we need to support large memory configurations */ - entry->busaddr[i] = dma_map_page(&pdev->dev, entry->pagelist[i], - 0, PAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(&pdev->dev, entry->busaddr[i])) { - DRM_ERROR("unable to map PCIGART pages!\n"); - drm_ati_pcigart_cleanup(dev, gart_info); - address = NULL; - bus_address = 0; - ret = -ENOMEM; - goto done; - } - page_base = (u32) entry->busaddr[i]; - - for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { - u32 offset; - u32 val; - - switch(gart_info->gart_reg_if) { - case DRM_ATI_GART_IGP: - val = page_base | 0xc; - break; - case DRM_ATI_GART_PCIE: - val = (page_base >> 8) | 0xc; - break; - default: - case DRM_ATI_GART_PCI: - val = page_base; - break; - } - if (gart_info->gart_table_location == - DRM_ATI_GART_MAIN) { - pci_gart[gart_idx] = cpu_to_le32(val); - } else { - offset = gart_idx * sizeof(u32); - writel(val, (void __iomem *)map->handle + offset); - } - gart_idx++; - page_base += ATI_PCIGART_PAGE_SIZE; - } - } - ret = 0; - -#ifdef CONFIG_X86 - wbinvd(); -#else - mb(); -#endif - - done: - gart_info->addr = address; - gart_info->bus_addr = bus_address; - return ret; -} diff --git a/drivers/gpu/drm/r128/ati_pcigart.h b/drivers/gpu/drm/r128/ati_pcigart.h deleted file mode 100644 index a728a1364e66..000000000000 --- a/drivers/gpu/drm/r128/ati_pcigart.h +++ /dev/null @@ -1,31 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef DRM_ATI_PCIGART_H -#define DRM_ATI_PCIGART_H - -#include - -/* location of GART table */ -#define DRM_ATI_GART_MAIN 1 -#define DRM_ATI_GART_FB 2 - -#define DRM_ATI_GART_PCI 1 -#define DRM_ATI_GART_PCIE 2 -#define DRM_ATI_GART_IGP 3 - -struct drm_ati_pcigart_info { - int gart_table_location; - int gart_reg_if; - void *addr; - dma_addr_t bus_addr; - dma_addr_t table_mask; - struct drm_dma_handle *table_handle; - struct drm_local_map mapping; - int table_size; -}; - -extern int drm_ati_pcigart_init(struct drm_device *dev, - struct drm_ati_pcigart_info * gart_info); -extern int drm_ati_pcigart_cleanup(struct drm_device *dev, - struct drm_ati_pcigart_info * gart_info); - -#endif diff --git a/drivers/gpu/drm/r128/r128_cce.c b/drivers/gpu/drm/r128/r128_cce.c deleted file mode 100644 index c04d84a69dd2..000000000000 --- a/drivers/gpu/drm/r128/r128_cce.c +++ /dev/null @@ -1,944 +0,0 @@ -/* r128_cce.c -- ATI Rage 128 driver -*- linux-c -*- - * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com - */ -/* - * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Gareth Hughes - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "r128_drv.h" - -#define R128_FIFO_DEBUG 0 - -#define FIRMWARE_NAME "r128/r128_cce.bin" - -MODULE_FIRMWARE(FIRMWARE_NAME); - -static int R128_READ_PLL(struct drm_device *dev, int addr) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - - R128_WRITE8(R128_CLOCK_CNTL_INDEX, addr & 0x1f); - return R128_READ(R128_CLOCK_CNTL_DATA); -} - -#if R128_FIFO_DEBUG -static void r128_status(drm_r128_private_t *dev_priv) -{ - printk("GUI_STAT = 0x%08x\n", - (unsigned int)R128_READ(R128_GUI_STAT)); - printk("PM4_STAT = 0x%08x\n", - (unsigned int)R128_READ(R128_PM4_STAT)); - printk("PM4_BUFFER_DL_WPTR = 0x%08x\n", - (unsigned int)R128_READ(R128_PM4_BUFFER_DL_WPTR)); - printk("PM4_BUFFER_DL_RPTR = 0x%08x\n", - (unsigned int)R128_READ(R128_PM4_BUFFER_DL_RPTR)); - printk("PM4_MICRO_CNTL = 0x%08x\n", - (unsigned int)R128_READ(R128_PM4_MICRO_CNTL)); - printk("PM4_BUFFER_CNTL = 0x%08x\n", - (unsigned int)R128_READ(R128_PM4_BUFFER_CNTL)); -} -#endif - -/* ================================================================ - * Engine, FIFO control - */ - -static int r128_do_pixcache_flush(drm_r128_private_t *dev_priv) -{ - u32 tmp; - int i; - - tmp = R128_READ(R128_PC_NGUI_CTLSTAT) | R128_PC_FLUSH_ALL; - R128_WRITE(R128_PC_NGUI_CTLSTAT, tmp); - - for (i = 0; i < dev_priv->usec_timeout; i++) { - if (!(R128_READ(R128_PC_NGUI_CTLSTAT) & R128_PC_BUSY)) - return 0; - udelay(1); - } - -#if R128_FIFO_DEBUG - DRM_ERROR("failed!\n"); -#endif - return -EBUSY; -} - -static int r128_do_wait_for_fifo(drm_r128_private_t *dev_priv, int entries) -{ - int i; - - for (i = 0; i < dev_priv->usec_timeout; i++) { - int slots = R128_READ(R128_GUI_STAT) & R128_GUI_FIFOCNT_MASK; - if (slots >= entries) - return 0; - udelay(1); - } - -#if R128_FIFO_DEBUG - DRM_ERROR("failed!\n"); -#endif - return -EBUSY; -} - -static int r128_do_wait_for_idle(drm_r128_private_t *dev_priv) -{ - int i, ret; - - ret = r128_do_wait_for_fifo(dev_priv, 64); - if (ret) - return ret; - - for (i = 0; i < dev_priv->usec_timeout; i++) { - if (!(R128_READ(R128_GUI_STAT) & R128_GUI_ACTIVE)) { - r128_do_pixcache_flush(dev_priv); - return 0; - } - udelay(1); - } - -#if R128_FIFO_DEBUG - DRM_ERROR("failed!\n"); -#endif - return -EBUSY; -} - -/* ================================================================ - * CCE control, initialization - */ - -/* Load the microcode for the CCE */ -static int r128_cce_load_microcode(drm_r128_private_t *dev_priv) -{ - struct platform_device *pdev; - const struct firmware *fw; - const __be32 *fw_data; - int rc, i; - - DRM_DEBUG("\n"); - - pdev = platform_device_register_simple("r128_cce", 0, NULL, 0); - if (IS_ERR(pdev)) { - pr_err("r128_cce: Failed to register firmware\n"); - return PTR_ERR(pdev); - } - rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev); - platform_device_unregister(pdev); - if (rc) { - pr_err("r128_cce: Failed to load firmware \"%s\"\n", - FIRMWARE_NAME); - return rc; - } - - if (fw->size != 256 * 8) { - pr_err("r128_cce: Bogus length %zu in firmware \"%s\"\n", - fw->size, FIRMWARE_NAME); - rc = -EINVAL; - goto out_release; - } - - r128_do_wait_for_idle(dev_priv); - - fw_data = (const __be32 *)fw->data; - R128_WRITE(R128_PM4_MICROCODE_ADDR, 0); - for (i = 0; i < 256; i++) { - R128_WRITE(R128_PM4_MICROCODE_DATAH, - be32_to_cpup(&fw_data[i * 2])); - R128_WRITE(R128_PM4_MICROCODE_DATAL, - be32_to_cpup(&fw_data[i * 2 + 1])); - } - -out_release: - release_firmware(fw); - return rc; -} - -/* Flush any pending commands to the CCE. This should only be used just - * prior to a wait for idle, as it informs the engine that the command - * stream is ending. - */ -static void r128_do_cce_flush(drm_r128_private_t *dev_priv) -{ - u32 tmp; - - tmp = R128_READ(R128_PM4_BUFFER_DL_WPTR) | R128_PM4_BUFFER_DL_DONE; - R128_WRITE(R128_PM4_BUFFER_DL_WPTR, tmp); -} - -/* Wait for the CCE to go idle. - */ -int r128_do_cce_idle(drm_r128_private_t *dev_priv) -{ - int i; - - for (i = 0; i < dev_priv->usec_timeout; i++) { - if (GET_RING_HEAD(dev_priv) == dev_priv->ring.tail) { - int pm4stat = R128_READ(R128_PM4_STAT); - if (((pm4stat & R128_PM4_FIFOCNT_MASK) >= - dev_priv->cce_fifo_size) && - !(pm4stat & (R128_PM4_BUSY | - R128_PM4_GUI_ACTIVE))) { - return r128_do_pixcache_flush(dev_priv); - } - } - udelay(1); - } - -#if R128_FIFO_DEBUG - DRM_ERROR("failed!\n"); - r128_status(dev_priv); -#endif - return -EBUSY; -} - -/* Start the Concurrent Command Engine. - */ -static void r128_do_cce_start(drm_r128_private_t *dev_priv) -{ - r128_do_wait_for_idle(dev_priv); - - R128_WRITE(R128_PM4_BUFFER_CNTL, - dev_priv->cce_mode | dev_priv->ring.size_l2qw - | R128_PM4_BUFFER_CNTL_NOUPDATE); - R128_READ(R128_PM4_BUFFER_ADDR); /* as per the sample code */ - R128_WRITE(R128_PM4_MICRO_CNTL, R128_PM4_MICRO_FREERUN); - - dev_priv->cce_running = 1; -} - -/* Reset the Concurrent Command Engine. This will not flush any pending - * commands, so you must wait for the CCE command stream to complete - * before calling this routine. - */ -static void r128_do_cce_reset(drm_r128_private_t *dev_priv) -{ - R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); - R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); - dev_priv->ring.tail = 0; -} - -/* Stop the Concurrent Command Engine. This will not flush any pending - * commands, so you must flush the command stream and wait for the CCE - * to go idle before calling this routine. - */ -static void r128_do_cce_stop(drm_r128_private_t *dev_priv) -{ - R128_WRITE(R128_PM4_MICRO_CNTL, 0); - R128_WRITE(R128_PM4_BUFFER_CNTL, - R128_PM4_NONPM4 | R128_PM4_BUFFER_CNTL_NOUPDATE); - - dev_priv->cce_running = 0; -} - -/* Reset the engine. This will stop the CCE if it is running. - */ -static int r128_do_engine_reset(struct drm_device *dev) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - u32 clock_cntl_index, mclk_cntl, gen_reset_cntl; - - r128_do_pixcache_flush(dev_priv); - - clock_cntl_index = R128_READ(R128_CLOCK_CNTL_INDEX); - mclk_cntl = R128_READ_PLL(dev, R128_MCLK_CNTL); - - R128_WRITE_PLL(R128_MCLK_CNTL, - mclk_cntl | R128_FORCE_GCP | R128_FORCE_PIPE3D_CP); - - gen_reset_cntl = R128_READ(R128_GEN_RESET_CNTL); - - /* Taken from the sample code - do not change */ - R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl | R128_SOFT_RESET_GUI); - R128_READ(R128_GEN_RESET_CNTL); - R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl & ~R128_SOFT_RESET_GUI); - R128_READ(R128_GEN_RESET_CNTL); - - R128_WRITE_PLL(R128_MCLK_CNTL, mclk_cntl); - R128_WRITE(R128_CLOCK_CNTL_INDEX, clock_cntl_index); - R128_WRITE(R128_GEN_RESET_CNTL, gen_reset_cntl); - - /* Reset the CCE ring */ - r128_do_cce_reset(dev_priv); - - /* The CCE is no longer running after an engine reset */ - dev_priv->cce_running = 0; - - /* Reset any pending vertex, indirect buffers */ - r128_freelist_reset(dev); - - return 0; -} - -static void r128_cce_init_ring_buffer(struct drm_device *dev, - drm_r128_private_t *dev_priv) -{ - u32 ring_start; - u32 tmp; - - DRM_DEBUG("\n"); - - /* The manual (p. 2) says this address is in "VM space". This - * means it's an offset from the start of AGP space. - */ -#if IS_ENABLED(CONFIG_AGP) - if (!dev_priv->is_pci) - ring_start = dev_priv->cce_ring->offset - dev->agp->base; - else -#endif - ring_start = dev_priv->cce_ring->offset - - (unsigned long)dev->sg->virtual; - - R128_WRITE(R128_PM4_BUFFER_OFFSET, ring_start | R128_AGP_OFFSET); - - R128_WRITE(R128_PM4_BUFFER_DL_WPTR, 0); - R128_WRITE(R128_PM4_BUFFER_DL_RPTR, 0); - - /* Set watermark control */ - R128_WRITE(R128_PM4_BUFFER_WM_CNTL, - ((R128_WATERMARK_L / 4) << R128_WMA_SHIFT) - | ((R128_WATERMARK_M / 4) << R128_WMB_SHIFT) - | ((R128_WATERMARK_N / 4) << R128_WMC_SHIFT) - | ((R128_WATERMARK_K / 64) << R128_WB_WM_SHIFT)); - - /* Force read. Why? Because it's in the examples... */ - R128_READ(R128_PM4_BUFFER_ADDR); - - /* Turn on bus mastering */ - tmp = R128_READ(R128_BUS_CNTL) & ~R128_BUS_MASTER_DIS; - R128_WRITE(R128_BUS_CNTL, tmp); -} - -static int r128_do_init_cce(struct drm_device *dev, drm_r128_init_t *init) -{ - drm_r128_private_t *dev_priv; - int rc; - - DRM_DEBUG("\n"); - - if (dev->dev_private) { - DRM_DEBUG("called when already initialized\n"); - return -EINVAL; - } - - dev_priv = kzalloc(sizeof(drm_r128_private_t), GFP_KERNEL); - if (dev_priv == NULL) - return -ENOMEM; - - dev_priv->is_pci = init->is_pci; - - if (dev_priv->is_pci && !dev->sg) { - DRM_ERROR("PCI GART memory not allocated!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - - dev_priv->usec_timeout = init->usec_timeout; - if (dev_priv->usec_timeout < 1 || - dev_priv->usec_timeout > R128_MAX_USEC_TIMEOUT) { - DRM_DEBUG("TIMEOUT problem!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - - dev_priv->cce_mode = init->cce_mode; - - /* GH: Simple idle check. - */ - atomic_set(&dev_priv->idle_count, 0); - - /* We don't support anything other than bus-mastering ring mode, - * but the ring can be in either AGP or PCI space for the ring - * read pointer. - */ - if ((init->cce_mode != R128_PM4_192BM) && - (init->cce_mode != R128_PM4_128BM_64INDBM) && - (init->cce_mode != R128_PM4_64BM_128INDBM) && - (init->cce_mode != R128_PM4_64BM_64VCBM_64INDBM)) { - DRM_DEBUG("Bad cce_mode!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - - switch (init->cce_mode) { - case R128_PM4_NONPM4: - dev_priv->cce_fifo_size = 0; - break; - case R128_PM4_192PIO: - case R128_PM4_192BM: - dev_priv->cce_fifo_size = 192; - break; - case R128_PM4_128PIO_64INDBM: - case R128_PM4_128BM_64INDBM: - dev_priv->cce_fifo_size = 128; - break; - case R128_PM4_64PIO_128INDBM: - case R128_PM4_64BM_128INDBM: - case R128_PM4_64PIO_64VCBM_64INDBM: - case R128_PM4_64BM_64VCBM_64INDBM: - case R128_PM4_64PIO_64VCPIO_64INDPIO: - dev_priv->cce_fifo_size = 64; - break; - } - - switch (init->fb_bpp) { - case 16: - dev_priv->color_fmt = R128_DATATYPE_RGB565; - break; - case 32: - default: - dev_priv->color_fmt = R128_DATATYPE_ARGB8888; - break; - } - dev_priv->front_offset = init->front_offset; - dev_priv->front_pitch = init->front_pitch; - dev_priv->back_offset = init->back_offset; - dev_priv->back_pitch = init->back_pitch; - - switch (init->depth_bpp) { - case 16: - dev_priv->depth_fmt = R128_DATATYPE_RGB565; - break; - case 24: - case 32: - default: - dev_priv->depth_fmt = R128_DATATYPE_ARGB8888; - break; - } - dev_priv->depth_offset = init->depth_offset; - dev_priv->depth_pitch = init->depth_pitch; - dev_priv->span_offset = init->span_offset; - - dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch / 8) << 21) | - (dev_priv->front_offset >> 5)); - dev_priv->back_pitch_offset_c = (((dev_priv->back_pitch / 8) << 21) | - (dev_priv->back_offset >> 5)); - dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) | - (dev_priv->depth_offset >> 5) | - R128_DST_TILE); - dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch / 8) << 21) | - (dev_priv->span_offset >> 5)); - - dev_priv->sarea = drm_legacy_getsarea(dev); - if (!dev_priv->sarea) { - DRM_ERROR("could not find sarea!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - - dev_priv->mmio = drm_legacy_findmap(dev, init->mmio_offset); - if (!dev_priv->mmio) { - DRM_ERROR("could not find mmio region!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - dev_priv->cce_ring = drm_legacy_findmap(dev, init->ring_offset); - if (!dev_priv->cce_ring) { - DRM_ERROR("could not find cce ring region!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - dev_priv->ring_rptr = drm_legacy_findmap(dev, init->ring_rptr_offset); - if (!dev_priv->ring_rptr) { - DRM_ERROR("could not find ring read pointer!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - dev->agp_buffer_token = init->buffers_offset; - dev->agp_buffer_map = drm_legacy_findmap(dev, init->buffers_offset); - if (!dev->agp_buffer_map) { - DRM_ERROR("could not find dma buffer region!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - - if (!dev_priv->is_pci) { - dev_priv->agp_textures = - drm_legacy_findmap(dev, init->agp_textures_offset); - if (!dev_priv->agp_textures) { - DRM_ERROR("could not find agp texture region!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -EINVAL; - } - } - - dev_priv->sarea_priv = - (drm_r128_sarea_t *) ((u8 *) dev_priv->sarea->handle + - init->sarea_priv_offset); - -#if IS_ENABLED(CONFIG_AGP) - if (!dev_priv->is_pci) { - drm_legacy_ioremap_wc(dev_priv->cce_ring, dev); - drm_legacy_ioremap_wc(dev_priv->ring_rptr, dev); - drm_legacy_ioremap_wc(dev->agp_buffer_map, dev); - if (!dev_priv->cce_ring->handle || - !dev_priv->ring_rptr->handle || - !dev->agp_buffer_map->handle) { - DRM_ERROR("Could not ioremap agp regions!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return -ENOMEM; - } - } else -#endif - { - dev_priv->cce_ring->handle = - (void *)(unsigned long)dev_priv->cce_ring->offset; - dev_priv->ring_rptr->handle = - (void *)(unsigned long)dev_priv->ring_rptr->offset; - dev->agp_buffer_map->handle = - (void *)(unsigned long)dev->agp_buffer_map->offset; - } - -#if IS_ENABLED(CONFIG_AGP) - if (!dev_priv->is_pci) - dev_priv->cce_buffers_offset = dev->agp->base; - else -#endif - dev_priv->cce_buffers_offset = (unsigned long)dev->sg->virtual; - - dev_priv->ring.start = (u32 *) dev_priv->cce_ring->handle; - dev_priv->ring.end = ((u32 *) dev_priv->cce_ring->handle - + init->ring_size / sizeof(u32)); - dev_priv->ring.size = init->ring_size; - dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8); - - dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; - - dev_priv->ring.high_mark = 128; - - dev_priv->sarea_priv->last_frame = 0; - R128_WRITE(R128_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame); - - dev_priv->sarea_priv->last_dispatch = 0; - R128_WRITE(R128_LAST_DISPATCH_REG, dev_priv->sarea_priv->last_dispatch); - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->is_pci) { -#endif - dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); - dev_priv->gart_info.gart_table_location = DRM_ATI_GART_MAIN; - dev_priv->gart_info.table_size = R128_PCIGART_TABLE_SIZE; - dev_priv->gart_info.addr = NULL; - dev_priv->gart_info.bus_addr = 0; - dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; - rc = drm_ati_pcigart_init(dev, &dev_priv->gart_info); - if (rc) { - DRM_ERROR("failed to init PCI GART!\n"); - dev->dev_private = (void *)dev_priv; - r128_do_cleanup_cce(dev); - return rc; - } - R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr); -#if IS_ENABLED(CONFIG_AGP) - } -#endif - - r128_cce_init_ring_buffer(dev, dev_priv); - rc = r128_cce_load_microcode(dev_priv); - - dev->dev_private = (void *)dev_priv; - - r128_do_engine_reset(dev); - - if (rc) { - DRM_ERROR("Failed to load firmware!\n"); - r128_do_cleanup_cce(dev); - } - - return rc; -} - -int r128_do_cleanup_cce(struct drm_device *dev) -{ - - /* Make sure interrupts are disabled here because the uninstall ioctl - * may not have been called from userspace and after dev_private - * is freed, it's too late. - */ - if (dev->irq_enabled) - drm_legacy_irq_uninstall(dev); - - if (dev->dev_private) { - drm_r128_private_t *dev_priv = dev->dev_private; - -#if IS_ENABLED(CONFIG_AGP) - if (!dev_priv->is_pci) { - if (dev_priv->cce_ring != NULL) - drm_legacy_ioremapfree(dev_priv->cce_ring, dev); - if (dev_priv->ring_rptr != NULL) - drm_legacy_ioremapfree(dev_priv->ring_rptr, dev); - if (dev->agp_buffer_map != NULL) { - drm_legacy_ioremapfree(dev->agp_buffer_map, dev); - dev->agp_buffer_map = NULL; - } - } else -#endif - { - if (dev_priv->gart_info.bus_addr) - if (!drm_ati_pcigart_cleanup(dev, - &dev_priv->gart_info)) - DRM_ERROR - ("failed to cleanup PCI GART!\n"); - } - - kfree(dev->dev_private); - dev->dev_private = NULL; - } - - return 0; -} - -int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_init_t *init = data; - - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - switch (init->func) { - case R128_INIT_CCE: - return r128_do_init_cce(dev, init); - case R128_CLEANUP_CCE: - return r128_do_cleanup_cce(dev); - } - - return -EINVAL; -} - -int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { - DRM_DEBUG("while CCE running\n"); - return 0; - } - - r128_do_cce_start(dev_priv); - - return 0; -} - -/* Stop the CCE. The engine must have been idled before calling this - * routine. - */ -int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_cce_stop_t *stop = data; - int ret; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - /* Flush any pending CCE commands. This ensures any outstanding - * commands are exectuted by the engine before we turn it off. - */ - if (stop->flush) - r128_do_cce_flush(dev_priv); - - /* If we fail to make the engine go idle, we return an error - * code so that the DRM ioctl wrapper can try again. - */ - if (stop->idle) { - ret = r128_do_cce_idle(dev_priv); - if (ret) - return ret; - } - - /* Finally, we can turn off the CCE. If the engine isn't idle, - * we will get some dropped triangles as they won't be fully - * rendered before the CCE is shut down. - */ - r128_do_cce_stop(dev_priv); - - /* Reset the engine */ - r128_do_engine_reset(dev); - - return 0; -} - -/* Just reset the CCE ring. Called as part of an X Server engine reset. - */ -int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - r128_do_cce_reset(dev_priv); - - /* The CCE is no longer running after an engine reset */ - dev_priv->cce_running = 0; - - return 0; -} - -int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - if (dev_priv->cce_running) - r128_do_cce_flush(dev_priv); - - return r128_do_cce_idle(dev_priv); -} - -int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev->dev_private); - - return r128_do_engine_reset(dev); -} - -int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - return -EINVAL; -} - -/* ================================================================ - * Freelist management - */ -#define R128_BUFFER_USED 0xffffffff -#define R128_BUFFER_FREE 0 - -#if 0 -static int r128_freelist_init(struct drm_device *dev) -{ - struct drm_device_dma *dma = dev->dma; - drm_r128_private_t *dev_priv = dev->dev_private; - struct drm_buf *buf; - drm_r128_buf_priv_t *buf_priv; - drm_r128_freelist_t *entry; - int i; - - dev_priv->head = kzalloc(sizeof(drm_r128_freelist_t), GFP_KERNEL); - if (dev_priv->head == NULL) - return -ENOMEM; - - dev_priv->head->age = R128_BUFFER_USED; - - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - - entry = kmalloc(sizeof(drm_r128_freelist_t), GFP_KERNEL); - if (!entry) - return -ENOMEM; - - entry->age = R128_BUFFER_FREE; - entry->buf = buf; - entry->prev = dev_priv->head; - entry->next = dev_priv->head->next; - if (!entry->next) - dev_priv->tail = entry; - - buf_priv->discard = 0; - buf_priv->dispatched = 0; - buf_priv->list_entry = entry; - - dev_priv->head->next = entry; - - if (dev_priv->head->next) - dev_priv->head->next->prev = entry; - } - - return 0; - -} -#endif - -static struct drm_buf *r128_freelist_get(struct drm_device * dev) -{ - struct drm_device_dma *dma = dev->dma; - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_buf_priv_t *buf_priv; - struct drm_buf *buf; - int i, t; - - /* FIXME: Optimize -- use freelist code */ - - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - if (!buf->file_priv) - return buf; - } - - for (t = 0; t < dev_priv->usec_timeout; t++) { - u32 done_age = R128_READ(R128_LAST_DISPATCH_REG); - - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[i]; - buf_priv = buf->dev_private; - if (buf->pending && buf_priv->age <= done_age) { - /* The buffer has been processed, so it - * can now be used. - */ - buf->pending = 0; - return buf; - } - } - udelay(1); - } - - DRM_DEBUG("returning NULL!\n"); - return NULL; -} - -void r128_freelist_reset(struct drm_device *dev) -{ - struct drm_device_dma *dma = dev->dma; - int i; - - for (i = 0; i < dma->buf_count; i++) { - struct drm_buf *buf = dma->buflist[i]; - drm_r128_buf_priv_t *buf_priv = buf->dev_private; - buf_priv->age = 0; - } -} - -/* ================================================================ - * CCE command submission - */ - -int r128_wait_ring(drm_r128_private_t *dev_priv, int n) -{ - drm_r128_ring_buffer_t *ring = &dev_priv->ring; - int i; - - for (i = 0; i < dev_priv->usec_timeout; i++) { - r128_update_ring_snapshot(dev_priv); - if (ring->space >= n) - return 0; - udelay(1); - } - - /* FIXME: This is being ignored... */ - DRM_ERROR("failed!\n"); - return -EBUSY; -} - -static int r128_cce_get_buffers(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_dma *d) -{ - int i; - struct drm_buf *buf; - - for (i = d->granted_count; i < d->request_count; i++) { - buf = r128_freelist_get(dev); - if (!buf) - return -EAGAIN; - - buf->file_priv = file_priv; - - if (copy_to_user(&d->request_indices[i], &buf->idx, - sizeof(buf->idx))) - return -EFAULT; - if (copy_to_user(&d->request_sizes[i], &buf->total, - sizeof(buf->total))) - return -EFAULT; - - d->granted_count++; - } - return 0; -} - -int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - int ret = 0; - struct drm_dma *d = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - /* Please don't send us buffers. - */ - if (d->send_count != 0) { - DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - task_pid_nr(current), d->send_count); - return -EINVAL; - } - - /* We'll send you buffers. - */ - if (d->request_count < 0 || d->request_count > dma->buf_count) { - DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - task_pid_nr(current), d->request_count, dma->buf_count); - return -EINVAL; - } - - d->granted_count = 0; - - if (d->request_count) - ret = r128_cce_get_buffers(dev, file_priv, d); - - return ret; -} diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c deleted file mode 100644 index e35a3a1449bd..000000000000 --- a/drivers/gpu/drm/r128/r128_drv.c +++ /dev/null @@ -1,116 +0,0 @@ -/* r128_drv.c -- ATI Rage 128 driver -*- linux-c -*- - * Created: Mon Dec 13 09:47:27 1999 by faith@precisioninsight.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Rickard E. (Rik) Faith - * Gareth Hughes - */ - -#include -#include - -#include -#include -#include -#include -#include - -#include "r128_drv.h" - -static struct pci_device_id pciidlist[] = { - r128_PCI_IDS -}; - -static const struct file_operations r128_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = drm_legacy_mmap, - .poll = drm_poll, -#ifdef CONFIG_COMPAT - .compat_ioctl = r128_compat_ioctl, -#endif - .llseek = noop_llseek, -}; - -static struct drm_driver driver = { - .driver_features = - DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | DRIVER_LEGACY | - DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ, - .dev_priv_size = sizeof(drm_r128_buf_priv_t), - .load = r128_driver_load, - .preclose = r128_driver_preclose, - .lastclose = r128_driver_lastclose, - .get_vblank_counter = r128_get_vblank_counter, - .enable_vblank = r128_enable_vblank, - .disable_vblank = r128_disable_vblank, - .irq_preinstall = r128_driver_irq_preinstall, - .irq_postinstall = r128_driver_irq_postinstall, - .irq_uninstall = r128_driver_irq_uninstall, - .irq_handler = r128_driver_irq_handler, - .ioctls = r128_ioctls, - .dma_ioctl = r128_cce_buffers, - .fops = &r128_driver_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; - -int r128_driver_load(struct drm_device *dev, unsigned long flags) -{ - struct pci_dev *pdev = to_pci_dev(dev->dev); - - pci_set_master(pdev); - return drm_vblank_init(dev, 1); -} - -static struct pci_driver r128_pci_driver = { - .name = DRIVER_NAME, - .id_table = pciidlist, -}; - -static int __init r128_init(void) -{ - driver.num_ioctls = r128_max_ioctl; - - return drm_legacy_pci_init(&driver, &r128_pci_driver); -} - -static void __exit r128_exit(void) -{ - drm_legacy_pci_exit(&driver, &r128_pci_driver); -} - -module_init(r128_init); -module_exit(r128_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h deleted file mode 100644 index 970e192b0d51..000000000000 --- a/drivers/gpu/drm/r128/r128_drv.h +++ /dev/null @@ -1,544 +0,0 @@ -/* r128_drv.h -- Private header for r128 driver -*- linux-c -*- - * Created: Mon Dec 13 09:51:11 1999 by faith@precisioninsight.com - */ -/* - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Rickard E. (Rik) Faith - * Kevin E. Martin - * Gareth Hughes - * Michel Dänzer - */ - -#ifndef __R128_DRV_H__ -#define __R128_DRV_H__ - -#include -#include -#include - -#include -#include -#include - -#include "ati_pcigart.h" - -/* General customization: - */ -#define DRIVER_AUTHOR "Gareth Hughes, VA Linux Systems Inc." - -#define DRIVER_NAME "r128" -#define DRIVER_DESC "ATI Rage 128" -#define DRIVER_DATE "20030725" - -/* Interface history: - * - * ?? - ?? - * 2.4 - Add support for ycbcr textures (no new ioctls) - * 2.5 - Add FLIP ioctl, disable FULLSCREEN. - */ -#define DRIVER_MAJOR 2 -#define DRIVER_MINOR 5 -#define DRIVER_PATCHLEVEL 0 - -#define GET_RING_HEAD(dev_priv) R128_READ(R128_PM4_BUFFER_DL_RPTR) - -typedef struct drm_r128_freelist { - unsigned int age; - struct drm_buf *buf; - struct drm_r128_freelist *next; - struct drm_r128_freelist *prev; -} drm_r128_freelist_t; - -typedef struct drm_r128_ring_buffer { - u32 *start; - u32 *end; - int size; - int size_l2qw; - - u32 tail; - u32 tail_mask; - int space; - - int high_mark; -} drm_r128_ring_buffer_t; - -typedef struct drm_r128_private { - drm_r128_ring_buffer_t ring; - drm_r128_sarea_t *sarea_priv; - - int cce_mode; - int cce_fifo_size; - int cce_running; - - drm_r128_freelist_t *head; - drm_r128_freelist_t *tail; - - int usec_timeout; - int is_pci; - unsigned long cce_buffers_offset; - - atomic_t idle_count; - - int page_flipping; - int current_page; - u32 crtc_offset; - u32 crtc_offset_cntl; - - atomic_t vbl_received; - - u32 color_fmt; - unsigned int front_offset; - unsigned int front_pitch; - unsigned int back_offset; - unsigned int back_pitch; - - u32 depth_fmt; - unsigned int depth_offset; - unsigned int depth_pitch; - unsigned int span_offset; - - u32 front_pitch_offset_c; - u32 back_pitch_offset_c; - u32 depth_pitch_offset_c; - u32 span_pitch_offset_c; - - drm_local_map_t *sarea; - drm_local_map_t *mmio; - drm_local_map_t *cce_ring; - drm_local_map_t *ring_rptr; - drm_local_map_t *agp_textures; - struct drm_ati_pcigart_info gart_info; -} drm_r128_private_t; - -typedef struct drm_r128_buf_priv { - u32 age; - int prim; - int discard; - int dispatched; - drm_r128_freelist_t *list_entry; -} drm_r128_buf_priv_t; - -extern const struct drm_ioctl_desc r128_ioctls[]; -extern int r128_max_ioctl; - - /* r128_cce.c */ -extern int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); - -extern int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv); - -extern void r128_freelist_reset(struct drm_device *dev); - -extern int r128_wait_ring(drm_r128_private_t *dev_priv, int n); - -extern int r128_do_cce_idle(drm_r128_private_t *dev_priv); -extern int r128_do_cleanup_cce(struct drm_device *dev); - -extern int r128_enable_vblank(struct drm_device *dev, unsigned int pipe); -extern void r128_disable_vblank(struct drm_device *dev, unsigned int pipe); -extern u32 r128_get_vblank_counter(struct drm_device *dev, unsigned int pipe); -extern irqreturn_t r128_driver_irq_handler(int irq, void *arg); -extern void r128_driver_irq_preinstall(struct drm_device *dev); -extern int r128_driver_irq_postinstall(struct drm_device *dev); -extern void r128_driver_irq_uninstall(struct drm_device *dev); -extern void r128_driver_lastclose(struct drm_device *dev); -extern int r128_driver_load(struct drm_device *dev, unsigned long flags); -extern void r128_driver_preclose(struct drm_device *dev, - struct drm_file *file_priv); - -extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg); - -/* Register definitions, register access macros and drmAddMap constants - * for Rage 128 kernel driver. - */ - -#define R128_AUX_SC_CNTL 0x1660 -# define R128_AUX1_SC_EN (1 << 0) -# define R128_AUX1_SC_MODE_OR (0 << 1) -# define R128_AUX1_SC_MODE_NAND (1 << 1) -# define R128_AUX2_SC_EN (1 << 2) -# define R128_AUX2_SC_MODE_OR (0 << 3) -# define R128_AUX2_SC_MODE_NAND (1 << 3) -# define R128_AUX3_SC_EN (1 << 4) -# define R128_AUX3_SC_MODE_OR (0 << 5) -# define R128_AUX3_SC_MODE_NAND (1 << 5) -#define R128_AUX1_SC_LEFT 0x1664 -#define R128_AUX1_SC_RIGHT 0x1668 -#define R128_AUX1_SC_TOP 0x166c -#define R128_AUX1_SC_BOTTOM 0x1670 -#define R128_AUX2_SC_LEFT 0x1674 -#define R128_AUX2_SC_RIGHT 0x1678 -#define R128_AUX2_SC_TOP 0x167c -#define R128_AUX2_SC_BOTTOM 0x1680 -#define R128_AUX3_SC_LEFT 0x1684 -#define R128_AUX3_SC_RIGHT 0x1688 -#define R128_AUX3_SC_TOP 0x168c -#define R128_AUX3_SC_BOTTOM 0x1690 - -#define R128_BRUSH_DATA0 0x1480 -#define R128_BUS_CNTL 0x0030 -# define R128_BUS_MASTER_DIS (1 << 6) - -#define R128_CLOCK_CNTL_INDEX 0x0008 -#define R128_CLOCK_CNTL_DATA 0x000c -# define R128_PLL_WR_EN (1 << 7) -#define R128_CONSTANT_COLOR_C 0x1d34 -#define R128_CRTC_OFFSET 0x0224 -#define R128_CRTC_OFFSET_CNTL 0x0228 -# define R128_CRTC_OFFSET_FLIP_CNTL (1 << 16) - -#define R128_DP_GUI_MASTER_CNTL 0x146c -# define R128_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) -# define R128_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) -# define R128_GMC_BRUSH_SOLID_COLOR (13 << 4) -# define R128_GMC_BRUSH_NONE (15 << 4) -# define R128_GMC_DST_16BPP (4 << 8) -# define R128_GMC_DST_24BPP (5 << 8) -# define R128_GMC_DST_32BPP (6 << 8) -# define R128_GMC_DST_DATATYPE_SHIFT 8 -# define R128_GMC_SRC_DATATYPE_COLOR (3 << 12) -# define R128_DP_SRC_SOURCE_MEMORY (2 << 24) -# define R128_DP_SRC_SOURCE_HOST_DATA (3 << 24) -# define R128_GMC_CLR_CMP_CNTL_DIS (1 << 28) -# define R128_GMC_AUX_CLIP_DIS (1 << 29) -# define R128_GMC_WR_MSK_DIS (1 << 30) -# define R128_ROP3_S 0x00cc0000 -# define R128_ROP3_P 0x00f00000 -#define R128_DP_WRITE_MASK 0x16cc -#define R128_DST_PITCH_OFFSET_C 0x1c80 -# define R128_DST_TILE (1 << 31) - -#define R128_GEN_INT_CNTL 0x0040 -# define R128_CRTC_VBLANK_INT_EN (1 << 0) -#define R128_GEN_INT_STATUS 0x0044 -# define R128_CRTC_VBLANK_INT (1 << 0) -# define R128_CRTC_VBLANK_INT_AK (1 << 0) -#define R128_GEN_RESET_CNTL 0x00f0 -# define R128_SOFT_RESET_GUI (1 << 0) - -#define R128_GUI_SCRATCH_REG0 0x15e0 -#define R128_GUI_SCRATCH_REG1 0x15e4 -#define R128_GUI_SCRATCH_REG2 0x15e8 -#define R128_GUI_SCRATCH_REG3 0x15ec -#define R128_GUI_SCRATCH_REG4 0x15f0 -#define R128_GUI_SCRATCH_REG5 0x15f4 - -#define R128_GUI_STAT 0x1740 -# define R128_GUI_FIFOCNT_MASK 0x0fff -# define R128_GUI_ACTIVE (1 << 31) - -#define R128_MCLK_CNTL 0x000f -# define R128_FORCE_GCP (1 << 16) -# define R128_FORCE_PIPE3D_CP (1 << 17) -# define R128_FORCE_RCP (1 << 18) - -#define R128_PC_GUI_CTLSTAT 0x1748 -#define R128_PC_NGUI_CTLSTAT 0x0184 -# define R128_PC_FLUSH_GUI (3 << 0) -# define R128_PC_RI_GUI (1 << 2) -# define R128_PC_FLUSH_ALL 0x00ff -# define R128_PC_BUSY (1 << 31) - -#define R128_PCI_GART_PAGE 0x017c -#define R128_PRIM_TEX_CNTL_C 0x1cb0 - -#define R128_SCALE_3D_CNTL 0x1a00 -#define R128_SEC_TEX_CNTL_C 0x1d00 -#define R128_SEC_TEXTURE_BORDER_COLOR_C 0x1d3c -#define R128_SETUP_CNTL 0x1bc4 -#define R128_STEN_REF_MASK_C 0x1d40 - -#define R128_TEX_CNTL_C 0x1c9c -# define R128_TEX_CACHE_FLUSH (1 << 23) - -#define R128_WAIT_UNTIL 0x1720 -# define R128_EVENT_CRTC_OFFSET (1 << 0) -#define R128_WINDOW_XY_OFFSET 0x1bcc - -/* CCE registers - */ -#define R128_PM4_BUFFER_OFFSET 0x0700 -#define R128_PM4_BUFFER_CNTL 0x0704 -# define R128_PM4_MASK (15 << 28) -# define R128_PM4_NONPM4 (0 << 28) -# define R128_PM4_192PIO (1 << 28) -# define R128_PM4_192BM (2 << 28) -# define R128_PM4_128PIO_64INDBM (3 << 28) -# define R128_PM4_128BM_64INDBM (4 << 28) -# define R128_PM4_64PIO_128INDBM (5 << 28) -# define R128_PM4_64BM_128INDBM (6 << 28) -# define R128_PM4_64PIO_64VCBM_64INDBM (7 << 28) -# define R128_PM4_64BM_64VCBM_64INDBM (8U << 28) -# define R128_PM4_64PIO_64VCPIO_64INDPIO (15U << 28) -# define R128_PM4_BUFFER_CNTL_NOUPDATE (1 << 27) - -#define R128_PM4_BUFFER_WM_CNTL 0x0708 -# define R128_WMA_SHIFT 0 -# define R128_WMB_SHIFT 8 -# define R128_WMC_SHIFT 16 -# define R128_WB_WM_SHIFT 24 - -#define R128_PM4_BUFFER_DL_RPTR_ADDR 0x070c -#define R128_PM4_BUFFER_DL_RPTR 0x0710 -#define R128_PM4_BUFFER_DL_WPTR 0x0714 -# define R128_PM4_BUFFER_DL_DONE (1 << 31) - -#define R128_PM4_VC_FPU_SETUP 0x071c - -#define R128_PM4_IW_INDOFF 0x0738 -#define R128_PM4_IW_INDSIZE 0x073c - -#define R128_PM4_STAT 0x07b8 -# define R128_PM4_FIFOCNT_MASK 0x0fff -# define R128_PM4_BUSY (1 << 16) -# define R128_PM4_GUI_ACTIVE (1 << 31) - -#define R128_PM4_MICROCODE_ADDR 0x07d4 -#define R128_PM4_MICROCODE_RADDR 0x07d8 -#define R128_PM4_MICROCODE_DATAH 0x07dc -#define R128_PM4_MICROCODE_DATAL 0x07e0 - -#define R128_PM4_BUFFER_ADDR 0x07f0 -#define R128_PM4_MICRO_CNTL 0x07fc -# define R128_PM4_MICRO_FREERUN (1 << 30) - -#define R128_PM4_FIFO_DATA_EVEN 0x1000 -#define R128_PM4_FIFO_DATA_ODD 0x1004 - -/* CCE command packets - */ -#define R128_CCE_PACKET0 0x00000000 -#define R128_CCE_PACKET1 0x40000000 -#define R128_CCE_PACKET2 0x80000000 -#define R128_CCE_PACKET3 0xC0000000 -# define R128_CNTL_HOSTDATA_BLT 0x00009400 -# define R128_CNTL_PAINT_MULTI 0x00009A00 -# define R128_CNTL_BITBLT_MULTI 0x00009B00 -# define R128_3D_RNDR_GEN_INDX_PRIM 0x00002300 - -#define R128_CCE_PACKET_MASK 0xC0000000 -#define R128_CCE_PACKET_COUNT_MASK 0x3fff0000 -#define R128_CCE_PACKET0_REG_MASK 0x000007ff -#define R128_CCE_PACKET1_REG0_MASK 0x000007ff -#define R128_CCE_PACKET1_REG1_MASK 0x003ff800 - -#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE 0x00000000 -#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT 0x00000001 -#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE 0x00000002 -#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE 0x00000003 -#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004 -#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005 -#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006 -#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2 0x00000007 -#define R128_CCE_VC_CNTL_PRIM_WALK_IND 0x00000010 -#define R128_CCE_VC_CNTL_PRIM_WALK_LIST 0x00000020 -#define R128_CCE_VC_CNTL_PRIM_WALK_RING 0x00000030 -#define R128_CCE_VC_CNTL_NUM_SHIFT 16 - -#define R128_DATATYPE_VQ 0 -#define R128_DATATYPE_CI4 1 -#define R128_DATATYPE_CI8 2 -#define R128_DATATYPE_ARGB1555 3 -#define R128_DATATYPE_RGB565 4 -#define R128_DATATYPE_RGB888 5 -#define R128_DATATYPE_ARGB8888 6 -#define R128_DATATYPE_RGB332 7 -#define R128_DATATYPE_Y8 8 -#define R128_DATATYPE_RGB8 9 -#define R128_DATATYPE_CI16 10 -#define R128_DATATYPE_YVYU422 11 -#define R128_DATATYPE_VYUY422 12 -#define R128_DATATYPE_AYUV444 14 -#define R128_DATATYPE_ARGB4444 15 - -/* Constants */ -#define R128_AGP_OFFSET 0x02000000 - -#define R128_WATERMARK_L 16 -#define R128_WATERMARK_M 8 -#define R128_WATERMARK_N 8 -#define R128_WATERMARK_K 128 - -#define R128_MAX_USEC_TIMEOUT 100000 /* 100 ms */ - -#define R128_LAST_FRAME_REG R128_GUI_SCRATCH_REG0 -#define R128_LAST_DISPATCH_REG R128_GUI_SCRATCH_REG1 -#define R128_MAX_VB_AGE 0x7fffffff -#define R128_MAX_VB_VERTS (0xffff) - -#define R128_RING_HIGH_MARK 128 - -#define R128_PERFORMANCE_BOXES 0 - -#define R128_PCIGART_TABLE_SIZE 32768 - -#define R128_READ(reg) readl(((void __iomem *)dev_priv->mmio->handle) + (reg)) -#define R128_WRITE(reg, val) writel(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) -#define R128_READ8(reg) readb(((void __iomem *)dev_priv->mmio->handle) + (reg)) -#define R128_WRITE8(reg, val) writeb(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) - -#define R128_WRITE_PLL(addr, val) \ -do { \ - R128_WRITE8(R128_CLOCK_CNTL_INDEX, \ - ((addr) & 0x1f) | R128_PLL_WR_EN); \ - R128_WRITE(R128_CLOCK_CNTL_DATA, (val)); \ -} while (0) - -#define CCE_PACKET0(reg, n) (R128_CCE_PACKET0 | \ - ((n) << 16) | ((reg) >> 2)) -#define CCE_PACKET1(reg0, reg1) (R128_CCE_PACKET1 | \ - (((reg1) >> 2) << 11) | ((reg0) >> 2)) -#define CCE_PACKET2() (R128_CCE_PACKET2) -#define CCE_PACKET3(pkt, n) (R128_CCE_PACKET3 | \ - (pkt) | ((n) << 16)) - -static __inline__ void r128_update_ring_snapshot(drm_r128_private_t *dev_priv) -{ - drm_r128_ring_buffer_t *ring = &dev_priv->ring; - ring->space = (GET_RING_HEAD(dev_priv) - ring->tail) * sizeof(u32); - if (ring->space <= 0) - ring->space += ring->size; -} - -/* ================================================================ - * Misc helper macros - */ - -#define DEV_INIT_TEST_WITH_RETURN(_dev_priv) \ -do { \ - if (!_dev_priv) { \ - DRM_ERROR("called with no initialization\n"); \ - return -EINVAL; \ - } \ -} while (0) - -#define RING_SPACE_TEST_WITH_RETURN(dev_priv) \ -do { \ - drm_r128_ring_buffer_t *ring = &dev_priv->ring; int i; \ - if (ring->space < ring->high_mark) { \ - for (i = 0 ; i < dev_priv->usec_timeout ; i++) { \ - r128_update_ring_snapshot(dev_priv); \ - if (ring->space >= ring->high_mark) \ - goto __ring_space_done; \ - udelay(1); \ - } \ - DRM_ERROR("ring space check failed!\n"); \ - return -EBUSY; \ - } \ - __ring_space_done: \ - ; \ -} while (0) - -#define VB_AGE_TEST_WITH_RETURN(dev_priv) \ -do { \ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; \ - if (sarea_priv->last_dispatch >= R128_MAX_VB_AGE) { \ - int __ret = r128_do_cce_idle(dev_priv); \ - if (__ret) \ - return __ret; \ - sarea_priv->last_dispatch = 0; \ - r128_freelist_reset(dev); \ - } \ -} while (0) - -#define R128_WAIT_UNTIL_PAGE_FLIPPED() do { \ - OUT_RING(CCE_PACKET0(R128_WAIT_UNTIL, 0)); \ - OUT_RING(R128_EVENT_CRTC_OFFSET); \ -} while (0) - -/* ================================================================ - * Ring control - */ - -#define R128_VERBOSE 0 - -#define RING_LOCALS \ - int write, _nr; unsigned int tail_mask; volatile u32 *ring; - -#define BEGIN_RING(n) do { \ - if (R128_VERBOSE) \ - DRM_INFO("BEGIN_RING(%d)\n", (n)); \ - if (dev_priv->ring.space <= (n) * sizeof(u32)) { \ - COMMIT_RING(); \ - r128_wait_ring(dev_priv, (n) * sizeof(u32)); \ - } \ - _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ - ring = dev_priv->ring.start; \ - write = dev_priv->ring.tail; \ - tail_mask = dev_priv->ring.tail_mask; \ -} while (0) - -/* You can set this to zero if you want. If the card locks up, you'll - * need to keep this set. It works around a bug in early revs of the - * Rage 128 chipset, where the CCE would read 32 dwords past the end of - * the ring buffer before wrapping around. - */ -#define R128_BROKEN_CCE 1 - -#define ADVANCE_RING() do { \ - if (R128_VERBOSE) \ - DRM_INFO("ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ - write, dev_priv->ring.tail); \ - if (R128_BROKEN_CCE && write < 32) \ - memcpy(dev_priv->ring.end, \ - dev_priv->ring.start, \ - write * sizeof(u32)); \ - if (((dev_priv->ring.tail + _nr) & tail_mask) != write) \ - DRM_ERROR( \ - "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ - ((dev_priv->ring.tail + _nr) & tail_mask), \ - write, __LINE__); \ - else \ - dev_priv->ring.tail = write; \ -} while (0) - -#define COMMIT_RING() do { \ - if (R128_VERBOSE) \ - DRM_INFO("COMMIT_RING() tail=0x%06x\n", \ - dev_priv->ring.tail); \ - mb(); \ - R128_WRITE(R128_PM4_BUFFER_DL_WPTR, dev_priv->ring.tail); \ - R128_READ(R128_PM4_BUFFER_DL_WPTR); \ -} while (0) - -#define OUT_RING(x) do { \ - if (R128_VERBOSE) \ - DRM_INFO(" OUT_RING( 0x%08x ) at 0x%x\n", \ - (unsigned int)(x), write); \ - ring[write++] = cpu_to_le32(x); \ - write &= tail_mask; \ -} while (0) - -#endif /* __R128_DRV_H__ */ diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c deleted file mode 100644 index cdeb1db87222..000000000000 --- a/drivers/gpu/drm/r128/r128_ioc32.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * \file r128_ioc32.c - * - * 32-bit ioctl compatibility routines for the R128 DRM. - * - * \author Dave Airlie with code from patches by Egbert Eich - * - * Copyright (C) Paul Mackerras 2005 - * Copyright (C) Egbert Eich 2003,2004 - * Copyright (C) Dave Airlie 2005 - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#include - -#include - -#include "r128_drv.h" - -typedef struct drm_r128_init32 { - int func; - unsigned int sarea_priv_offset; - int is_pci; - int cce_mode; - int cce_secure; - int ring_size; - int usec_timeout; - - unsigned int fb_bpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - unsigned int depth_bpp; - unsigned int depth_offset, depth_pitch; - unsigned int span_offset; - - unsigned int fb_offset; - unsigned int mmio_offset; - unsigned int ring_offset; - unsigned int ring_rptr_offset; - unsigned int buffers_offset; - unsigned int agp_textures_offset; -} drm_r128_init32_t; - -static int compat_r128_init(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_r128_init32_t init32; - drm_r128_init_t init; - - if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) - return -EFAULT; - - init.func = init32.func; - init.sarea_priv_offset = init32.sarea_priv_offset; - init.is_pci = init32.is_pci; - init.cce_mode = init32.cce_mode; - init.cce_secure = init32.cce_secure; - init.ring_size = init32.ring_size; - init.usec_timeout = init32.usec_timeout; - init.fb_bpp = init32.fb_bpp; - init.front_offset = init32.front_offset; - init.front_pitch = init32.front_pitch; - init.back_offset = init32.back_offset; - init.back_pitch = init32.back_pitch; - init.depth_bpp = init32.depth_bpp; - init.depth_offset = init32.depth_offset; - init.depth_pitch = init32.depth_pitch; - init.span_offset = init32.span_offset; - init.fb_offset = init32.fb_offset; - init.mmio_offset = init32.mmio_offset; - init.ring_offset = init32.ring_offset; - init.ring_rptr_offset = init32.ring_rptr_offset; - init.buffers_offset = init32.buffers_offset; - init.agp_textures_offset = init32.agp_textures_offset; - - return drm_ioctl_kernel(file, r128_cce_init, &init, - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); -} - -typedef struct drm_r128_depth32 { - int func; - int n; - u32 x; - u32 y; - u32 buffer; - u32 mask; -} drm_r128_depth32_t; - -static int compat_r128_depth(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_r128_depth32_t depth32; - drm_r128_depth_t depth; - - if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32))) - return -EFAULT; - - depth.func = depth32.func; - depth.n = depth32.n; - depth.x = compat_ptr(depth32.x); - depth.y = compat_ptr(depth32.y); - depth.buffer = compat_ptr(depth32.buffer); - depth.mask = compat_ptr(depth32.mask); - - return drm_ioctl_kernel(file, r128_cce_depth, &depth, DRM_AUTH); -} - -typedef struct drm_r128_stipple32 { - u32 mask; -} drm_r128_stipple32_t; - -static int compat_r128_stipple(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_r128_stipple32_t stipple32; - drm_r128_stipple_t stipple; - - if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32))) - return -EFAULT; - - stipple.mask = compat_ptr(stipple32.mask); - - return drm_ioctl_kernel(file, r128_cce_stipple, &stipple, DRM_AUTH); -} - -typedef struct drm_r128_getparam32 { - int param; - u32 value; -} drm_r128_getparam32_t; - -static int compat_r128_getparam(struct file *file, unsigned int cmd, - unsigned long arg) -{ - drm_r128_getparam32_t getparam32; - drm_r128_getparam_t getparam; - - if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) - return -EFAULT; - - getparam.param = getparam32.param; - getparam.value = compat_ptr(getparam32.value); - - return drm_ioctl_kernel(file, r128_getparam, &getparam, DRM_AUTH); -} - -drm_ioctl_compat_t *r128_compat_ioctls[] = { - [DRM_R128_INIT] = compat_r128_init, - [DRM_R128_DEPTH] = compat_r128_depth, - [DRM_R128_STIPPLE] = compat_r128_stipple, - [DRM_R128_GETPARAM] = compat_r128_getparam, -}; - -/** - * r128_compat_ioctl - Called whenever a 32-bit process running under - * a 64-bit kernel performs an ioctl on /dev/dri/card. - * - * @filp: file pointer. - * @cmd: command. - * @arg: user argument. - * return: zero on success or negative number on failure. - */ -long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ - unsigned int nr = DRM_IOCTL_NR(cmd); - drm_ioctl_compat_t *fn = NULL; - int ret; - - if (nr < DRM_COMMAND_BASE) - return drm_compat_ioctl(filp, cmd, arg); - - if (nr < DRM_COMMAND_BASE + ARRAY_SIZE(r128_compat_ioctls)) - fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE]; - - if (fn != NULL) - ret = (*fn) (filp, cmd, arg); - else - ret = drm_ioctl(filp, cmd, arg); - - return ret; -} diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c deleted file mode 100644 index d84e9c96e20a..000000000000 --- a/drivers/gpu/drm/r128/r128_irq.c +++ /dev/null @@ -1,118 +0,0 @@ -/* r128_irq.c -- IRQ handling for radeon -*- linux-c -*- */ -/* - * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. - * - * The Weather Channel (TM) funded Tungsten Graphics to develop the - * initial release of the Radeon 8500 driver under the XFree86 license. - * This notice must be preserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell - * Eric Anholt - */ - -#include -#include -#include -#include - -#include "r128_drv.h" - -u32 r128_get_vblank_counter(struct drm_device *dev, unsigned int pipe) -{ - const drm_r128_private_t *dev_priv = dev->dev_private; - - if (pipe != 0) - return 0; - - return atomic_read(&dev_priv->vbl_received); -} - -irqreturn_t r128_driver_irq_handler(int irq, void *arg) -{ - struct drm_device *dev = (struct drm_device *) arg; - drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; - int status; - - status = R128_READ(R128_GEN_INT_STATUS); - - /* VBLANK interrupt */ - if (status & R128_CRTC_VBLANK_INT) { - R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); - atomic_inc(&dev_priv->vbl_received); - drm_handle_vblank(dev, 0); - return IRQ_HANDLED; - } - return IRQ_NONE; -} - -int r128_enable_vblank(struct drm_device *dev, unsigned int pipe) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - - if (pipe != 0) { - DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); - return -EINVAL; - } - - R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN); - return 0; -} - -void r128_disable_vblank(struct drm_device *dev, unsigned int pipe) -{ - if (pipe != 0) - DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); - - /* - * FIXME: implement proper interrupt disable by using the vblank - * counter register (if available) - * - * R128_WRITE(R128_GEN_INT_CNTL, - * R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN); - */ -} - -void r128_driver_irq_preinstall(struct drm_device *dev) -{ - drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; - - /* Disable *all* interrupts */ - R128_WRITE(R128_GEN_INT_CNTL, 0); - /* Clear vblank bit if it's already high */ - R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK); -} - -int r128_driver_irq_postinstall(struct drm_device *dev) -{ - return 0; -} - -void r128_driver_irq_uninstall(struct drm_device *dev) -{ - drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private; - if (!dev_priv) - return; - - /* Disable *all* interrupts */ - R128_WRITE(R128_GEN_INT_CNTL, 0); -} diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c deleted file mode 100644 index ac13fc2a0214..000000000000 --- a/drivers/gpu/drm/r128/r128_state.c +++ /dev/null @@ -1,1641 +0,0 @@ -/* r128_state.c -- State support for r128 -*- linux-c -*- - * Created: Thu Jan 27 02:53:43 2000 by gareth@valinux.com - */ -/* - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Gareth Hughes - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include "r128_drv.h" - -/* ================================================================ - * CCE hardware state programming functions - */ - -static void r128_emit_clip_rects(drm_r128_private_t *dev_priv, - struct drm_clip_rect *boxes, int count) -{ - u32 aux_sc_cntl = 0x00000000; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING((count < 3 ? count : 3) * 5 + 2); - - if (count >= 1) { - OUT_RING(CCE_PACKET0(R128_AUX1_SC_LEFT, 3)); - OUT_RING(boxes[0].x1); - OUT_RING(boxes[0].x2 - 1); - OUT_RING(boxes[0].y1); - OUT_RING(boxes[0].y2 - 1); - - aux_sc_cntl |= (R128_AUX1_SC_EN | R128_AUX1_SC_MODE_OR); - } - if (count >= 2) { - OUT_RING(CCE_PACKET0(R128_AUX2_SC_LEFT, 3)); - OUT_RING(boxes[1].x1); - OUT_RING(boxes[1].x2 - 1); - OUT_RING(boxes[1].y1); - OUT_RING(boxes[1].y2 - 1); - - aux_sc_cntl |= (R128_AUX2_SC_EN | R128_AUX2_SC_MODE_OR); - } - if (count >= 3) { - OUT_RING(CCE_PACKET0(R128_AUX3_SC_LEFT, 3)); - OUT_RING(boxes[2].x1); - OUT_RING(boxes[2].x2 - 1); - OUT_RING(boxes[2].y1); - OUT_RING(boxes[2].y2 - 1); - - aux_sc_cntl |= (R128_AUX3_SC_EN | R128_AUX3_SC_MODE_OR); - } - - OUT_RING(CCE_PACKET0(R128_AUX_SC_CNTL, 0)); - OUT_RING(aux_sc_cntl); - - ADVANCE_RING(); -} - -static __inline__ void r128_emit_core(drm_r128_private_t *dev_priv) -{ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_r128_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_SCALE_3D_CNTL, 0)); - OUT_RING(ctx->scale_3d_cntl); - - ADVANCE_RING(); -} - -static __inline__ void r128_emit_context(drm_r128_private_t *dev_priv) -{ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_r128_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(13); - - OUT_RING(CCE_PACKET0(R128_DST_PITCH_OFFSET_C, 11)); - OUT_RING(ctx->dst_pitch_offset_c); - OUT_RING(ctx->dp_gui_master_cntl_c); - OUT_RING(ctx->sc_top_left_c); - OUT_RING(ctx->sc_bottom_right_c); - OUT_RING(ctx->z_offset_c); - OUT_RING(ctx->z_pitch_c); - OUT_RING(ctx->z_sten_cntl_c); - OUT_RING(ctx->tex_cntl_c); - OUT_RING(ctx->misc_3d_state_cntl_reg); - OUT_RING(ctx->texture_clr_cmp_clr_c); - OUT_RING(ctx->texture_clr_cmp_msk_c); - OUT_RING(ctx->fog_color_c); - - ADVANCE_RING(); -} - -static __inline__ void r128_emit_setup(drm_r128_private_t *dev_priv) -{ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_r128_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(3); - - OUT_RING(CCE_PACKET1(R128_SETUP_CNTL, R128_PM4_VC_FPU_SETUP)); - OUT_RING(ctx->setup_cntl); - OUT_RING(ctx->pm4_vc_fpu_setup); - - ADVANCE_RING(); -} - -static __inline__ void r128_emit_masks(drm_r128_private_t *dev_priv) -{ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_r128_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(5); - - OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0)); - OUT_RING(ctx->dp_write_mask); - - OUT_RING(CCE_PACKET0(R128_STEN_REF_MASK_C, 1)); - OUT_RING(ctx->sten_ref_mask_c); - OUT_RING(ctx->plane_3d_mask_c); - - ADVANCE_RING(); -} - -static __inline__ void r128_emit_window(drm_r128_private_t *dev_priv) -{ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_r128_context_regs_t *ctx = &sarea_priv->context_state; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_WINDOW_XY_OFFSET, 0)); - OUT_RING(ctx->window_xy_offset); - - ADVANCE_RING(); -} - -static __inline__ void r128_emit_tex0(drm_r128_private_t *dev_priv) -{ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_r128_context_regs_t *ctx = &sarea_priv->context_state; - drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[0]; - int i; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(7 + R128_MAX_TEXTURE_LEVELS); - - OUT_RING(CCE_PACKET0(R128_PRIM_TEX_CNTL_C, - 2 + R128_MAX_TEXTURE_LEVELS)); - OUT_RING(tex->tex_cntl); - OUT_RING(tex->tex_combine_cntl); - OUT_RING(ctx->tex_size_pitch_c); - for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) - OUT_RING(tex->tex_offset[i]); - - OUT_RING(CCE_PACKET0(R128_CONSTANT_COLOR_C, 1)); - OUT_RING(ctx->constant_color_c); - OUT_RING(tex->tex_border_color); - - ADVANCE_RING(); -} - -static __inline__ void r128_emit_tex1(drm_r128_private_t *dev_priv) -{ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_r128_texture_regs_t *tex = &sarea_priv->tex_state[1]; - int i; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(5 + R128_MAX_TEXTURE_LEVELS); - - OUT_RING(CCE_PACKET0(R128_SEC_TEX_CNTL_C, 1 + R128_MAX_TEXTURE_LEVELS)); - OUT_RING(tex->tex_cntl); - OUT_RING(tex->tex_combine_cntl); - for (i = 0; i < R128_MAX_TEXTURE_LEVELS; i++) - OUT_RING(tex->tex_offset[i]); - - OUT_RING(CCE_PACKET0(R128_SEC_TEXTURE_BORDER_COLOR_C, 0)); - OUT_RING(tex->tex_border_color); - - ADVANCE_RING(); -} - -static void r128_emit_state(drm_r128_private_t *dev_priv) -{ - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - unsigned int dirty = sarea_priv->dirty; - - DRM_DEBUG("dirty=0x%08x\n", dirty); - - if (dirty & R128_UPLOAD_CORE) { - r128_emit_core(dev_priv); - sarea_priv->dirty &= ~R128_UPLOAD_CORE; - } - - if (dirty & R128_UPLOAD_CONTEXT) { - r128_emit_context(dev_priv); - sarea_priv->dirty &= ~R128_UPLOAD_CONTEXT; - } - - if (dirty & R128_UPLOAD_SETUP) { - r128_emit_setup(dev_priv); - sarea_priv->dirty &= ~R128_UPLOAD_SETUP; - } - - if (dirty & R128_UPLOAD_MASKS) { - r128_emit_masks(dev_priv); - sarea_priv->dirty &= ~R128_UPLOAD_MASKS; - } - - if (dirty & R128_UPLOAD_WINDOW) { - r128_emit_window(dev_priv); - sarea_priv->dirty &= ~R128_UPLOAD_WINDOW; - } - - if (dirty & R128_UPLOAD_TEX0) { - r128_emit_tex0(dev_priv); - sarea_priv->dirty &= ~R128_UPLOAD_TEX0; - } - - if (dirty & R128_UPLOAD_TEX1) { - r128_emit_tex1(dev_priv); - sarea_priv->dirty &= ~R128_UPLOAD_TEX1; - } - - /* Turn off the texture cache flushing */ - sarea_priv->context_state.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH; - - sarea_priv->dirty &= ~R128_REQUIRE_QUIESCENCE; -} - -#if R128_PERFORMANCE_BOXES -/* ================================================================ - * Performance monitoring functions - */ - -static void r128_clear_box(drm_r128_private_t *dev_priv, - int x, int y, int w, int h, int r, int g, int b) -{ - u32 pitch, offset; - u32 fb_bpp, color; - RING_LOCALS; - - switch (dev_priv->fb_bpp) { - case 16: - fb_bpp = R128_GMC_DST_16BPP; - color = (((r & 0xf8) << 8) | - ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); - break; - case 24: - fb_bpp = R128_GMC_DST_24BPP; - color = ((r << 16) | (g << 8) | b); - break; - case 32: - fb_bpp = R128_GMC_DST_32BPP; - color = (((0xff) << 24) | (r << 16) | (g << 8) | b); - break; - default: - return; - } - - offset = dev_priv->back_offset; - pitch = dev_priv->back_pitch >> 3; - - BEGIN_RING(6); - - OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); - OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - fb_bpp | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_P | - R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS); - - OUT_RING((pitch << 21) | (offset >> 5)); - OUT_RING(color); - - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); -} - -static void r128_cce_performance_boxes(drm_r128_private_t *dev_priv) -{ - if (atomic_read(&dev_priv->idle_count) == 0) - r128_clear_box(dev_priv, 64, 4, 8, 8, 0, 255, 0); - else - atomic_set(&dev_priv->idle_count, 0); -} - -#endif - -/* ================================================================ - * CCE command dispatch functions - */ - -static void r128_print_dirty(const char *msg, unsigned int flags) -{ - DRM_INFO("%s: (0x%x) %s%s%s%s%s%s%s%s%s\n", - msg, - flags, - (flags & R128_UPLOAD_CORE) ? "core, " : "", - (flags & R128_UPLOAD_CONTEXT) ? "context, " : "", - (flags & R128_UPLOAD_SETUP) ? "setup, " : "", - (flags & R128_UPLOAD_TEX0) ? "tex0, " : "", - (flags & R128_UPLOAD_TEX1) ? "tex1, " : "", - (flags & R128_UPLOAD_MASKS) ? "masks, " : "", - (flags & R128_UPLOAD_WINDOW) ? "window, " : "", - (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "", - (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : ""); -} - -static void r128_cce_dispatch_clear(struct drm_device *dev, - drm_r128_clear_t *clear) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - int nbox = sarea_priv->nbox; - struct drm_clip_rect *pbox = sarea_priv->boxes; - unsigned int flags = clear->flags; - int i; - RING_LOCALS; - DRM_DEBUG("\n"); - - if (dev_priv->page_flipping && dev_priv->current_page == 1) { - unsigned int tmp = flags; - - flags &= ~(R128_FRONT | R128_BACK); - if (tmp & R128_FRONT) - flags |= R128_BACK; - if (tmp & R128_BACK) - flags |= R128_FRONT; - } - - for (i = 0; i < nbox; i++) { - int x = pbox[i].x1; - int y = pbox[i].y1; - int w = pbox[i].x2 - x; - int h = pbox[i].y2 - y; - - DRM_DEBUG("dispatch clear %d,%d-%d,%d flags 0x%x\n", - pbox[i].x1, pbox[i].y1, pbox[i].x2, - pbox[i].y2, flags); - - if (flags & (R128_FRONT | R128_BACK)) { - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_DP_WRITE_MASK, 0)); - OUT_RING(clear->color_mask); - - ADVANCE_RING(); - } - - if (flags & R128_FRONT) { - BEGIN_RING(6); - - OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); - OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - (dev_priv->color_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_P | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_AUX_CLIP_DIS); - - OUT_RING(dev_priv->front_pitch_offset_c); - OUT_RING(clear->clear_color); - - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); - } - - if (flags & R128_BACK) { - BEGIN_RING(6); - - OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); - OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - (dev_priv->color_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_P | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_AUX_CLIP_DIS); - - OUT_RING(dev_priv->back_pitch_offset_c); - OUT_RING(clear->clear_color); - - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); - } - - if (flags & R128_DEPTH) { - BEGIN_RING(6); - - OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); - OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - (dev_priv->depth_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_P | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS); - - OUT_RING(dev_priv->depth_pitch_offset_c); - OUT_RING(clear->clear_depth); - - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); - } - } -} - -static void r128_cce_dispatch_swap(struct drm_device *dev) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - int nbox = sarea_priv->nbox; - struct drm_clip_rect *pbox = sarea_priv->boxes; - int i; - RING_LOCALS; - DRM_DEBUG("\n"); - -#if R128_PERFORMANCE_BOXES - /* Do some trivial performance monitoring... - */ - r128_cce_performance_boxes(dev_priv); -#endif - - for (i = 0; i < nbox; i++) { - int x = pbox[i].x1; - int y = pbox[i].y1; - int w = pbox[i].x2 - x; - int h = pbox[i].y2 - y; - - BEGIN_RING(7); - - OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); - OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | - R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_NONE | - (dev_priv->color_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_S | - R128_DP_SRC_SOURCE_MEMORY | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS); - - /* Make this work even if front & back are flipped: - */ - if (dev_priv->current_page == 0) { - OUT_RING(dev_priv->back_pitch_offset_c); - OUT_RING(dev_priv->front_pitch_offset_c); - } else { - OUT_RING(dev_priv->front_pitch_offset_c); - OUT_RING(dev_priv->back_pitch_offset_c); - } - - OUT_RING((x << 16) | y); - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); - } - - /* Increment the frame counter. The client-side 3D driver must - * throttle the framerate by waiting for this value before - * performing the swapbuffer ioctl. - */ - dev_priv->sarea_priv->last_frame++; - - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0)); - OUT_RING(dev_priv->sarea_priv->last_frame); - - ADVANCE_RING(); -} - -static void r128_cce_dispatch_flip(struct drm_device *dev) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - DRM_DEBUG("page=%d pfCurrentPage=%d\n", - dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); - -#if R128_PERFORMANCE_BOXES - /* Do some trivial performance monitoring... - */ - r128_cce_performance_boxes(dev_priv); -#endif - - BEGIN_RING(4); - - R128_WAIT_UNTIL_PAGE_FLIPPED(); - OUT_RING(CCE_PACKET0(R128_CRTC_OFFSET, 0)); - - if (dev_priv->current_page == 0) - OUT_RING(dev_priv->back_offset); - else - OUT_RING(dev_priv->front_offset); - - ADVANCE_RING(); - - /* Increment the frame counter. The client-side 3D driver must - * throttle the framerate by waiting for this value before - * performing the swapbuffer ioctl. - */ - dev_priv->sarea_priv->last_frame++; - dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = - 1 - dev_priv->current_page; - - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_LAST_FRAME_REG, 0)); - OUT_RING(dev_priv->sarea_priv->last_frame); - - ADVANCE_RING(); -} - -static void r128_cce_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_buf_priv_t *buf_priv = buf->dev_private; - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - int format = sarea_priv->vc_format; - int offset = buf->bus_address; - int size = buf->used; - int prim = buf_priv->prim; - int i = 0; - RING_LOCALS; - DRM_DEBUG("buf=%d nbox=%d\n", buf->idx, sarea_priv->nbox); - - if (0) - r128_print_dirty("dispatch_vertex", sarea_priv->dirty); - - if (buf->used) { - buf_priv->dispatched = 1; - - if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) - r128_emit_state(dev_priv); - - do { - /* Emit the next set of up to three cliprects */ - if (i < sarea_priv->nbox) { - r128_emit_clip_rects(dev_priv, - &sarea_priv->boxes[i], - sarea_priv->nbox - i); - } - - /* Emit the vertex buffer rendering commands */ - BEGIN_RING(5); - - OUT_RING(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, 3)); - OUT_RING(offset); - OUT_RING(size); - OUT_RING(format); - OUT_RING(prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST | - (size << R128_CCE_VC_CNTL_NUM_SHIFT)); - - ADVANCE_RING(); - - i += 3; - } while (i < sarea_priv->nbox); - } - - if (buf_priv->discard) { - buf_priv->age = dev_priv->sarea_priv->last_dispatch; - - /* Emit the vertex buffer age */ - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); - OUT_RING(buf_priv->age); - - ADVANCE_RING(); - - buf->pending = 1; - buf->used = 0; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; - } - - dev_priv->sarea_priv->last_dispatch++; - - sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; - sarea_priv->nbox = 0; -} - -static void r128_cce_dispatch_indirect(struct drm_device *dev, - struct drm_buf *buf, int start, int end) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_buf_priv_t *buf_priv = buf->dev_private; - RING_LOCALS; - DRM_DEBUG("indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); - - if (start != end) { - int offset = buf->bus_address + start; - int dwords = (end - start + 3) / sizeof(u32); - - /* Indirect buffer data must be an even number of - * dwords, so if we've been given an odd number we must - * pad the data with a Type-2 CCE packet. - */ - if (dwords & 1) { - u32 *data = (u32 *) - ((char *)dev->agp_buffer_map->handle - + buf->offset + start); - data[dwords++] = cpu_to_le32(R128_CCE_PACKET2); - } - - buf_priv->dispatched = 1; - - /* Fire off the indirect buffer */ - BEGIN_RING(3); - - OUT_RING(CCE_PACKET0(R128_PM4_IW_INDOFF, 1)); - OUT_RING(offset); - OUT_RING(dwords); - - ADVANCE_RING(); - } - - if (buf_priv->discard) { - buf_priv->age = dev_priv->sarea_priv->last_dispatch; - - /* Emit the indirect buffer age */ - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); - OUT_RING(buf_priv->age); - - ADVANCE_RING(); - - buf->pending = 1; - buf->used = 0; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; - } - - dev_priv->sarea_priv->last_dispatch++; -} - -static void r128_cce_dispatch_indices(struct drm_device *dev, - struct drm_buf *buf, - int start, int end, int count) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_buf_priv_t *buf_priv = buf->dev_private; - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - int format = sarea_priv->vc_format; - int offset = dev->agp_buffer_map->offset - dev_priv->cce_buffers_offset; - int prim = buf_priv->prim; - u32 *data; - int dwords; - int i = 0; - RING_LOCALS; - DRM_DEBUG("indices: s=%d e=%d c=%d\n", start, end, count); - - if (0) - r128_print_dirty("dispatch_indices", sarea_priv->dirty); - - if (start != end) { - buf_priv->dispatched = 1; - - if (sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS) - r128_emit_state(dev_priv); - - dwords = (end - start + 3) / sizeof(u32); - - data = (u32 *) ((char *)dev->agp_buffer_map->handle - + buf->offset + start); - - data[0] = cpu_to_le32(CCE_PACKET3(R128_3D_RNDR_GEN_INDX_PRIM, - dwords - 2)); - - data[1] = cpu_to_le32(offset); - data[2] = cpu_to_le32(R128_MAX_VB_VERTS); - data[3] = cpu_to_le32(format); - data[4] = cpu_to_le32((prim | R128_CCE_VC_CNTL_PRIM_WALK_IND | - (count << 16))); - - if (count & 0x1) { -#ifdef __LITTLE_ENDIAN - data[dwords - 1] &= 0x0000ffff; -#else - data[dwords - 1] &= 0xffff0000; -#endif - } - - do { - /* Emit the next set of up to three cliprects */ - if (i < sarea_priv->nbox) { - r128_emit_clip_rects(dev_priv, - &sarea_priv->boxes[i], - sarea_priv->nbox - i); - } - - r128_cce_dispatch_indirect(dev, buf, start, end); - - i += 3; - } while (i < sarea_priv->nbox); - } - - if (buf_priv->discard) { - buf_priv->age = dev_priv->sarea_priv->last_dispatch; - - /* Emit the vertex buffer age */ - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_LAST_DISPATCH_REG, 0)); - OUT_RING(buf_priv->age); - - ADVANCE_RING(); - - buf->pending = 1; - /* FIXME: Check dispatched field */ - buf_priv->dispatched = 0; - } - - dev_priv->sarea_priv->last_dispatch++; - - sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; - sarea_priv->nbox = 0; -} - -static int r128_cce_dispatch_blit(struct drm_device *dev, - struct drm_file *file_priv, - drm_r128_blit_t *blit) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_r128_buf_priv_t *buf_priv; - u32 *data; - int dword_shift, dwords; - RING_LOCALS; - DRM_DEBUG("\n"); - - /* The compiler won't optimize away a division by a variable, - * even if the only legal values are powers of two. Thus, we'll - * use a shift instead. - */ - switch (blit->format) { - case R128_DATATYPE_ARGB8888: - dword_shift = 0; - break; - case R128_DATATYPE_ARGB1555: - case R128_DATATYPE_RGB565: - case R128_DATATYPE_ARGB4444: - case R128_DATATYPE_YVYU422: - case R128_DATATYPE_VYUY422: - dword_shift = 1; - break; - case R128_DATATYPE_CI8: - case R128_DATATYPE_RGB8: - dword_shift = 2; - break; - default: - DRM_ERROR("invalid blit format %d\n", blit->format); - return -EINVAL; - } - - /* Flush the pixel cache, and mark the contents as Read Invalid. - * This ensures no pixel data gets mixed up with the texture - * data from the host data blit, otherwise part of the texture - * image may be corrupted. - */ - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0)); - OUT_RING(R128_PC_RI_GUI | R128_PC_FLUSH_GUI); - - ADVANCE_RING(); - - /* Dispatch the indirect buffer. - */ - buf = dma->buflist[blit->idx]; - buf_priv = buf->dev_private; - - if (buf->file_priv != file_priv) { - DRM_ERROR("process %d using buffer owned by %p\n", - task_pid_nr(current), buf->file_priv); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", blit->idx); - return -EINVAL; - } - - buf_priv->discard = 1; - - dwords = (blit->width * blit->height) >> dword_shift; - - data = (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); - - data[0] = cpu_to_le32(CCE_PACKET3(R128_CNTL_HOSTDATA_BLT, dwords + 6)); - data[1] = cpu_to_le32((R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_NONE | - (blit->format << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_S | - R128_DP_SRC_SOURCE_HOST_DATA | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS)); - - data[2] = cpu_to_le32((blit->pitch << 21) | (blit->offset >> 5)); - data[3] = cpu_to_le32(0xffffffff); - data[4] = cpu_to_le32(0xffffffff); - data[5] = cpu_to_le32((blit->y << 16) | blit->x); - data[6] = cpu_to_le32((blit->height << 16) | blit->width); - data[7] = cpu_to_le32(dwords); - - buf->used = (dwords + 8) * sizeof(u32); - - r128_cce_dispatch_indirect(dev, buf, 0, buf->used); - - /* Flush the pixel cache after the blit completes. This ensures - * the texture data is written out to memory before rendering - * continues. - */ - BEGIN_RING(2); - - OUT_RING(CCE_PACKET0(R128_PC_GUI_CTLSTAT, 0)); - OUT_RING(R128_PC_FLUSH_GUI); - - ADVANCE_RING(); - - return 0; -} - -/* ================================================================ - * Tiled depth buffer management - * - * FIXME: These should all set the destination write mask for when we - * have hardware stencil support. - */ - -static int r128_cce_dispatch_write_span(struct drm_device *dev, - drm_r128_depth_t *depth) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - int count, x, y; - u32 *buffer; - u8 *mask; - int i, buffer_size, mask_size; - RING_LOCALS; - DRM_DEBUG("\n"); - - count = depth->n; - if (count > 4096 || count <= 0) - return -EMSGSIZE; - - if (copy_from_user(&x, depth->x, sizeof(x))) - return -EFAULT; - if (copy_from_user(&y, depth->y, sizeof(y))) - return -EFAULT; - - buffer_size = depth->n * sizeof(u32); - buffer = memdup_user(depth->buffer, buffer_size); - if (IS_ERR(buffer)) - return PTR_ERR(buffer); - - mask_size = depth->n; - if (depth->mask) { - mask = memdup_user(depth->mask, mask_size); - if (IS_ERR(mask)) { - kfree(buffer); - return PTR_ERR(mask); - } - - for (i = 0; i < count; i++, x++) { - if (mask[i]) { - BEGIN_RING(6); - - OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); - OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - (dev_priv->depth_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_P | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_WR_MSK_DIS); - - OUT_RING(dev_priv->depth_pitch_offset_c); - OUT_RING(buffer[i]); - - OUT_RING((x << 16) | y); - OUT_RING((1 << 16) | 1); - - ADVANCE_RING(); - } - } - - kfree(mask); - } else { - for (i = 0; i < count; i++, x++) { - BEGIN_RING(6); - - OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); - OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - (dev_priv->depth_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_P | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_WR_MSK_DIS); - - OUT_RING(dev_priv->depth_pitch_offset_c); - OUT_RING(buffer[i]); - - OUT_RING((x << 16) | y); - OUT_RING((1 << 16) | 1); - - ADVANCE_RING(); - } - } - - kfree(buffer); - - return 0; -} - -static int r128_cce_dispatch_write_pixels(struct drm_device *dev, - drm_r128_depth_t *depth) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - int count, *x, *y; - u32 *buffer; - u8 *mask; - int i, xbuf_size, ybuf_size, buffer_size, mask_size; - RING_LOCALS; - DRM_DEBUG("\n"); - - count = depth->n; - if (count > 4096 || count <= 0) - return -EMSGSIZE; - - xbuf_size = count * sizeof(*x); - ybuf_size = count * sizeof(*y); - x = memdup_user(depth->x, xbuf_size); - if (IS_ERR(x)) - return PTR_ERR(x); - y = memdup_user(depth->y, ybuf_size); - if (IS_ERR(y)) { - kfree(x); - return PTR_ERR(y); - } - buffer_size = depth->n * sizeof(u32); - buffer = memdup_user(depth->buffer, buffer_size); - if (IS_ERR(buffer)) { - kfree(x); - kfree(y); - return PTR_ERR(buffer); - } - - if (depth->mask) { - mask_size = depth->n; - mask = memdup_user(depth->mask, mask_size); - if (IS_ERR(mask)) { - kfree(x); - kfree(y); - kfree(buffer); - return PTR_ERR(mask); - } - - for (i = 0; i < count; i++) { - if (mask[i]) { - BEGIN_RING(6); - - OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); - OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - (dev_priv->depth_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_P | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_WR_MSK_DIS); - - OUT_RING(dev_priv->depth_pitch_offset_c); - OUT_RING(buffer[i]); - - OUT_RING((x[i] << 16) | y[i]); - OUT_RING((1 << 16) | 1); - - ADVANCE_RING(); - } - } - - kfree(mask); - } else { - for (i = 0; i < count; i++) { - BEGIN_RING(6); - - OUT_RING(CCE_PACKET3(R128_CNTL_PAINT_MULTI, 4)); - OUT_RING(R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_SOLID_COLOR | - (dev_priv->depth_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_P | - R128_GMC_CLR_CMP_CNTL_DIS | - R128_GMC_WR_MSK_DIS); - - OUT_RING(dev_priv->depth_pitch_offset_c); - OUT_RING(buffer[i]); - - OUT_RING((x[i] << 16) | y[i]); - OUT_RING((1 << 16) | 1); - - ADVANCE_RING(); - } - } - - kfree(x); - kfree(y); - kfree(buffer); - - return 0; -} - -static int r128_cce_dispatch_read_span(struct drm_device *dev, - drm_r128_depth_t *depth) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - int count, x, y; - RING_LOCALS; - DRM_DEBUG("\n"); - - count = depth->n; - if (count > 4096 || count <= 0) - return -EMSGSIZE; - - if (copy_from_user(&x, depth->x, sizeof(x))) - return -EFAULT; - if (copy_from_user(&y, depth->y, sizeof(y))) - return -EFAULT; - - BEGIN_RING(7); - - OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); - OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | - R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_NONE | - (dev_priv->depth_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_S | - R128_DP_SRC_SOURCE_MEMORY | - R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); - - OUT_RING(dev_priv->depth_pitch_offset_c); - OUT_RING(dev_priv->span_pitch_offset_c); - - OUT_RING((x << 16) | y); - OUT_RING((0 << 16) | 0); - OUT_RING((count << 16) | 1); - - ADVANCE_RING(); - - return 0; -} - -static int r128_cce_dispatch_read_pixels(struct drm_device *dev, - drm_r128_depth_t *depth) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - int count, *x, *y; - int i, xbuf_size, ybuf_size; - RING_LOCALS; - DRM_DEBUG("\n"); - - count = depth->n; - if (count > 4096 || count <= 0) - return -EMSGSIZE; - - if (count > dev_priv->depth_pitch) - count = dev_priv->depth_pitch; - - xbuf_size = count * sizeof(*x); - ybuf_size = count * sizeof(*y); - x = kmalloc(xbuf_size, GFP_KERNEL); - if (x == NULL) - return -ENOMEM; - y = kmalloc(ybuf_size, GFP_KERNEL); - if (y == NULL) { - kfree(x); - return -ENOMEM; - } - if (copy_from_user(x, depth->x, xbuf_size)) { - kfree(x); - kfree(y); - return -EFAULT; - } - if (copy_from_user(y, depth->y, ybuf_size)) { - kfree(x); - kfree(y); - return -EFAULT; - } - - for (i = 0; i < count; i++) { - BEGIN_RING(7); - - OUT_RING(CCE_PACKET3(R128_CNTL_BITBLT_MULTI, 5)); - OUT_RING(R128_GMC_SRC_PITCH_OFFSET_CNTL | - R128_GMC_DST_PITCH_OFFSET_CNTL | - R128_GMC_BRUSH_NONE | - (dev_priv->depth_fmt << 8) | - R128_GMC_SRC_DATATYPE_COLOR | - R128_ROP3_S | - R128_DP_SRC_SOURCE_MEMORY | - R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS); - - OUT_RING(dev_priv->depth_pitch_offset_c); - OUT_RING(dev_priv->span_pitch_offset_c); - - OUT_RING((x[i] << 16) | y[i]); - OUT_RING((i << 16) | 0); - OUT_RING((1 << 16) | 1); - - ADVANCE_RING(); - } - - kfree(x); - kfree(y); - - return 0; -} - -/* ================================================================ - * Polygon stipple - */ - -static void r128_cce_dispatch_stipple(struct drm_device *dev, u32 *stipple) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - int i; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(33); - - OUT_RING(CCE_PACKET0(R128_BRUSH_DATA0, 31)); - for (i = 0; i < 32; i++) - OUT_RING(stipple[i]); - - ADVANCE_RING(); -} - -/* ================================================================ - * IOCTL functions - */ - -static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_sarea_t *sarea_priv; - drm_r128_clear_t *clear = data; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - sarea_priv = dev_priv->sarea_priv; - - if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; - - r128_cce_dispatch_clear(dev, clear); - COMMIT_RING(); - - /* Make sure we restore the 3D state next time. - */ - dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; - - return 0; -} - -static int r128_do_init_pageflip(struct drm_device *dev) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - dev_priv->crtc_offset = R128_READ(R128_CRTC_OFFSET); - dev_priv->crtc_offset_cntl = R128_READ(R128_CRTC_OFFSET_CNTL); - - R128_WRITE(R128_CRTC_OFFSET, dev_priv->front_offset); - R128_WRITE(R128_CRTC_OFFSET_CNTL, - dev_priv->crtc_offset_cntl | R128_CRTC_OFFSET_FLIP_CNTL); - - dev_priv->page_flipping = 1; - dev_priv->current_page = 0; - dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; - - return 0; -} - -static int r128_do_cleanup_pageflip(struct drm_device *dev) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - R128_WRITE(R128_CRTC_OFFSET, dev_priv->crtc_offset); - R128_WRITE(R128_CRTC_OFFSET_CNTL, dev_priv->crtc_offset_cntl); - - if (dev_priv->current_page != 0) { - r128_cce_dispatch_flip(dev); - COMMIT_RING(); - } - - dev_priv->page_flipping = 0; - return 0; -} - -/* Swapping and flipping are different operations, need different ioctls. - * They can & should be intermixed to support multiple 3d windows. - */ - -static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - if (!dev_priv->page_flipping) - r128_do_init_pageflip(dev); - - r128_cce_dispatch_flip(dev); - - COMMIT_RING(); - return 0; -} - -static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; - - r128_cce_dispatch_swap(dev); - dev_priv->sarea_priv->dirty |= (R128_UPLOAD_CONTEXT | - R128_UPLOAD_MASKS); - - COMMIT_RING(); - return 0; -} - -static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_r128_buf_priv_t *buf_priv; - drm_r128_vertex_t *vertex = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", - task_pid_nr(current), vertex->idx, vertex->count, vertex->discard); - - if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - vertex->idx, dma->buf_count - 1); - return -EINVAL; - } - if (vertex->prim < 0 || - vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { - DRM_ERROR("buffer prim %d\n", vertex->prim); - return -EINVAL; - } - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - buf = dma->buflist[vertex->idx]; - buf_priv = buf->dev_private; - - if (buf->file_priv != file_priv) { - DRM_ERROR("process %d using buffer owned by %p\n", - task_pid_nr(current), buf->file_priv); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex->idx); - return -EINVAL; - } - - buf->used = vertex->count; - buf_priv->prim = vertex->prim; - buf_priv->discard = vertex->discard; - - r128_cce_dispatch_vertex(dev, buf); - - COMMIT_RING(); - return 0; -} - -static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_r128_buf_priv_t *buf_priv; - drm_r128_indices_t *elts = data; - int count; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", task_pid_nr(current), - elts->idx, elts->start, elts->end, elts->discard); - - if (elts->idx < 0 || elts->idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - elts->idx, dma->buf_count - 1); - return -EINVAL; - } - if (elts->prim < 0 || - elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { - DRM_ERROR("buffer prim %d\n", elts->prim); - return -EINVAL; - } - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - buf = dma->buflist[elts->idx]; - buf_priv = buf->dev_private; - - if (buf->file_priv != file_priv) { - DRM_ERROR("process %d using buffer owned by %p\n", - task_pid_nr(current), buf->file_priv); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", elts->idx); - return -EINVAL; - } - - count = (elts->end - elts->start) / sizeof(u16); - elts->start -= R128_INDEX_PRIM_OFFSET; - - if (elts->start & 0x7) { - DRM_ERROR("misaligned buffer 0x%x\n", elts->start); - return -EINVAL; - } - if (elts->start < buf->used) { - DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); - return -EINVAL; - } - - buf->used = elts->end; - buf_priv->prim = elts->prim; - buf_priv->discard = elts->discard; - - r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count); - - COMMIT_RING(); - return 0; -} - -static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_blit_t *blit = data; - int ret; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - DRM_DEBUG("pid=%d index=%d\n", task_pid_nr(current), blit->idx); - - if (blit->idx < 0 || blit->idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - blit->idx, dma->buf_count - 1); - return -EINVAL; - } - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - ret = r128_cce_dispatch_blit(dev, file_priv, blit); - - COMMIT_RING(); - return ret; -} - -int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_depth_t *depth = data; - int ret; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - ret = -EINVAL; - switch (depth->func) { - case R128_WRITE_SPAN: - ret = r128_cce_dispatch_write_span(dev, depth); - break; - case R128_WRITE_PIXELS: - ret = r128_cce_dispatch_write_pixels(dev, depth); - break; - case R128_READ_SPAN: - ret = r128_cce_dispatch_read_span(dev, depth); - break; - case R128_READ_PIXELS: - ret = r128_cce_dispatch_read_pixels(dev, depth); - break; - } - - COMMIT_RING(); - return ret; -} - -int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_stipple_t *stipple = data; - u32 mask[32]; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32))) - return -EFAULT; - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - r128_cce_dispatch_stipple(dev, mask); - - COMMIT_RING(); - return 0; -} - -static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_r128_buf_priv_t *buf_priv; - drm_r128_indirect_t *indirect = data; -#if 0 - RING_LOCALS; -#endif - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", - indirect->idx, indirect->start, indirect->end, - indirect->discard); - - if (indirect->idx < 0 || indirect->idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - indirect->idx, dma->buf_count - 1); - return -EINVAL; - } - - buf = dma->buflist[indirect->idx]; - buf_priv = buf->dev_private; - - if (buf->file_priv != file_priv) { - DRM_ERROR("process %d using buffer owned by %p\n", - task_pid_nr(current), buf->file_priv); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", indirect->idx); - return -EINVAL; - } - - if (indirect->start < buf->used) { - DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", - indirect->start, buf->used); - return -EINVAL; - } - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - buf->used = indirect->end; - buf_priv->discard = indirect->discard; - -#if 0 - /* Wait for the 3D stream to idle before the indirect buffer - * containing 2D acceleration commands is processed. - */ - BEGIN_RING(2); - RADEON_WAIT_UNTIL_3D_IDLE(); - ADVANCE_RING(); -#endif - - /* Dispatch the indirect buffer full of commands from the - * X server. This is insecure and is thus only available to - * privileged clients. - */ - r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end); - - COMMIT_RING(); - return 0; -} - -int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_getparam_t *param = data; - struct pci_dev *pdev = to_pci_dev(dev->dev); - int value; - - DEV_INIT_TEST_WITH_RETURN(dev_priv); - - DRM_DEBUG("pid=%d\n", task_pid_nr(current)); - - switch (param->param) { - case R128_PARAM_IRQ_NR: - value = pdev->irq; - break; - default: - return -EINVAL; - } - - if (copy_to_user(param->value, &value, sizeof(int))) { - DRM_ERROR("copy_to_user\n"); - return -EFAULT; - } - - return 0; -} - -void r128_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) -{ - if (dev->dev_private) { - drm_r128_private_t *dev_priv = dev->dev_private; - if (dev_priv->page_flipping) - r128_do_cleanup_pageflip(dev); - } -} -void r128_driver_lastclose(struct drm_device *dev) -{ - r128_do_cleanup_cce(dev); -} - -const struct drm_ioctl_desc r128_ioctls[] = { - DRM_IOCTL_DEF_DRV(R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(R128_CCE_IDLE, r128_cce_idle, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_RESET, r128_engine_reset, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_FULLSCREEN, r128_fullscreen, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_SWAP, r128_cce_swap, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_FLIP, r128_cce_flip, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_CLEAR, r128_cce_clear, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_VERTEX, r128_cce_vertex, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_INDICES, r128_cce_indices, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_BLIT, r128_cce_blit, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_DEPTH, r128_cce_depth, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_STIPPLE, r128_cce_stipple, DRM_AUTH), - DRM_IOCTL_DEF_DRV(R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(R128_GETPARAM, r128_getparam, DRM_AUTH), -}; - -int r128_max_ioctl = ARRAY_SIZE(r128_ioctls); diff --git a/include/uapi/drm/r128_drm.h b/include/uapi/drm/r128_drm.h deleted file mode 100644 index 690e9c62f510..000000000000 --- a/include/uapi/drm/r128_drm.h +++ /dev/null @@ -1,336 +0,0 @@ -/* r128_drm.h -- Public header for the r128 driver -*- linux-c -*- - * Created: Wed Apr 5 19:24:19 2000 by kevin@precisioninsight.com - */ -/* - * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Authors: - * Gareth Hughes - * Kevin E. Martin - */ - -#ifndef __R128_DRM_H__ -#define __R128_DRM_H__ - -#include "drm.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -/* WARNING: If you change any of these defines, make sure to change the - * defines in the X server file (r128_sarea.h) - */ -#ifndef __R128_SAREA_DEFINES__ -#define __R128_SAREA_DEFINES__ - -/* What needs to be changed for the current vertex buffer? - */ -#define R128_UPLOAD_CONTEXT 0x001 -#define R128_UPLOAD_SETUP 0x002 -#define R128_UPLOAD_TEX0 0x004 -#define R128_UPLOAD_TEX1 0x008 -#define R128_UPLOAD_TEX0IMAGES 0x010 -#define R128_UPLOAD_TEX1IMAGES 0x020 -#define R128_UPLOAD_CORE 0x040 -#define R128_UPLOAD_MASKS 0x080 -#define R128_UPLOAD_WINDOW 0x100 -#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */ -#define R128_REQUIRE_QUIESCENCE 0x400 -#define R128_UPLOAD_ALL 0x7ff - -#define R128_FRONT 0x1 -#define R128_BACK 0x2 -#define R128_DEPTH 0x4 - -/* Primitive types - */ -#define R128_POINTS 0x1 -#define R128_LINES 0x2 -#define R128_LINE_STRIP 0x3 -#define R128_TRIANGLES 0x4 -#define R128_TRIANGLE_FAN 0x5 -#define R128_TRIANGLE_STRIP 0x6 - -/* Vertex/indirect buffer size - */ -#define R128_BUFFER_SIZE 16384 - -/* Byte offsets for indirect buffer data - */ -#define R128_INDEX_PRIM_OFFSET 20 -#define R128_HOSTDATA_BLIT_OFFSET 32 - -/* Keep these small for testing. - */ -#define R128_NR_SAREA_CLIPRECTS 12 - -/* There are 2 heaps (local/AGP). Each region within a heap is a - * minimum of 64k, and there are at most 64 of them per heap. - */ -#define R128_LOCAL_TEX_HEAP 0 -#define R128_AGP_TEX_HEAP 1 -#define R128_NR_TEX_HEAPS 2 -#define R128_NR_TEX_REGIONS 64 -#define R128_LOG_TEX_GRANULARITY 16 - -#define R128_NR_CONTEXT_REGS 12 - -#define R128_MAX_TEXTURE_LEVELS 11 -#define R128_MAX_TEXTURE_UNITS 2 - -#endif /* __R128_SAREA_DEFINES__ */ - -typedef struct { - /* Context state - can be written in one large chunk */ - unsigned int dst_pitch_offset_c; - unsigned int dp_gui_master_cntl_c; - unsigned int sc_top_left_c; - unsigned int sc_bottom_right_c; - unsigned int z_offset_c; - unsigned int z_pitch_c; - unsigned int z_sten_cntl_c; - unsigned int tex_cntl_c; - unsigned int misc_3d_state_cntl_reg; - unsigned int texture_clr_cmp_clr_c; - unsigned int texture_clr_cmp_msk_c; - unsigned int fog_color_c; - - /* Texture state */ - unsigned int tex_size_pitch_c; - unsigned int constant_color_c; - - /* Setup state */ - unsigned int pm4_vc_fpu_setup; - unsigned int setup_cntl; - - /* Mask state */ - unsigned int dp_write_mask; - unsigned int sten_ref_mask_c; - unsigned int plane_3d_mask_c; - - /* Window state */ - unsigned int window_xy_offset; - - /* Core state */ - unsigned int scale_3d_cntl; -} drm_r128_context_regs_t; - -/* Setup registers for each texture unit - */ -typedef struct { - unsigned int tex_cntl; - unsigned int tex_combine_cntl; - unsigned int tex_size_pitch; - unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS]; - unsigned int tex_border_color; -} drm_r128_texture_regs_t; - -typedef struct drm_r128_sarea { - /* The channel for communication of state information to the kernel - * on firing a vertex buffer. - */ - drm_r128_context_regs_t context_state; - drm_r128_texture_regs_t tex_state[R128_MAX_TEXTURE_UNITS]; - unsigned int dirty; - unsigned int vertsize; - unsigned int vc_format; - - /* The current cliprects, or a subset thereof. - */ - struct drm_clip_rect boxes[R128_NR_SAREA_CLIPRECTS]; - unsigned int nbox; - - /* Counters for client-side throttling of rendering clients. - */ - unsigned int last_frame; - unsigned int last_dispatch; - - struct drm_tex_region tex_list[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS + 1]; - unsigned int tex_age[R128_NR_TEX_HEAPS]; - int ctx_owner; - int pfAllowPageFlip; /* number of 3d windows (0,1,2 or more) */ - int pfCurrentPage; /* which buffer is being displayed? */ -} drm_r128_sarea_t; - -/* WARNING: If you change any of these defines, make sure to change the - * defines in the Xserver file (xf86drmR128.h) - */ - -/* Rage 128 specific ioctls - * The device specific ioctl range is 0x40 to 0x79. - */ -#define DRM_R128_INIT 0x00 -#define DRM_R128_CCE_START 0x01 -#define DRM_R128_CCE_STOP 0x02 -#define DRM_R128_CCE_RESET 0x03 -#define DRM_R128_CCE_IDLE 0x04 -/* 0x05 not used */ -#define DRM_R128_RESET 0x06 -#define DRM_R128_SWAP 0x07 -#define DRM_R128_CLEAR 0x08 -#define DRM_R128_VERTEX 0x09 -#define DRM_R128_INDICES 0x0a -#define DRM_R128_BLIT 0x0b -#define DRM_R128_DEPTH 0x0c -#define DRM_R128_STIPPLE 0x0d -/* 0x0e not used */ -#define DRM_R128_INDIRECT 0x0f -#define DRM_R128_FULLSCREEN 0x10 -#define DRM_R128_CLEAR2 0x11 -#define DRM_R128_GETPARAM 0x12 -#define DRM_R128_FLIP 0x13 - -#define DRM_IOCTL_R128_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INIT, drm_r128_init_t) -#define DRM_IOCTL_R128_CCE_START DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_START) -#define DRM_IOCTL_R128_CCE_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CCE_STOP, drm_r128_cce_stop_t) -#define DRM_IOCTL_R128_CCE_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_RESET) -#define DRM_IOCTL_R128_CCE_IDLE DRM_IO( DRM_COMMAND_BASE + DRM_R128_CCE_IDLE) -/* 0x05 not used */ -#define DRM_IOCTL_R128_RESET DRM_IO( DRM_COMMAND_BASE + DRM_R128_RESET) -#define DRM_IOCTL_R128_SWAP DRM_IO( DRM_COMMAND_BASE + DRM_R128_SWAP) -#define DRM_IOCTL_R128_CLEAR DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR, drm_r128_clear_t) -#define DRM_IOCTL_R128_VERTEX DRM_IOW( DRM_COMMAND_BASE + DRM_R128_VERTEX, drm_r128_vertex_t) -#define DRM_IOCTL_R128_INDICES DRM_IOW( DRM_COMMAND_BASE + DRM_R128_INDICES, drm_r128_indices_t) -#define DRM_IOCTL_R128_BLIT DRM_IOW( DRM_COMMAND_BASE + DRM_R128_BLIT, drm_r128_blit_t) -#define DRM_IOCTL_R128_DEPTH DRM_IOW( DRM_COMMAND_BASE + DRM_R128_DEPTH, drm_r128_depth_t) -#define DRM_IOCTL_R128_STIPPLE DRM_IOW( DRM_COMMAND_BASE + DRM_R128_STIPPLE, drm_r128_stipple_t) -/* 0x0e not used */ -#define DRM_IOCTL_R128_INDIRECT DRM_IOWR(DRM_COMMAND_BASE + DRM_R128_INDIRECT, drm_r128_indirect_t) -#define DRM_IOCTL_R128_FULLSCREEN DRM_IOW( DRM_COMMAND_BASE + DRM_R128_FULLSCREEN, drm_r128_fullscreen_t) -#define DRM_IOCTL_R128_CLEAR2 DRM_IOW( DRM_COMMAND_BASE + DRM_R128_CLEAR2, drm_r128_clear2_t) -#define DRM_IOCTL_R128_GETPARAM DRM_IOWR( DRM_COMMAND_BASE + DRM_R128_GETPARAM, drm_r128_getparam_t) -#define DRM_IOCTL_R128_FLIP DRM_IO( DRM_COMMAND_BASE + DRM_R128_FLIP) - -typedef struct drm_r128_init { - enum { - R128_INIT_CCE = 0x01, - R128_CLEANUP_CCE = 0x02 - } func; - unsigned long sarea_priv_offset; - int is_pci; - int cce_mode; - int cce_secure; - int ring_size; - int usec_timeout; - - unsigned int fb_bpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - unsigned int depth_bpp; - unsigned int depth_offset, depth_pitch; - unsigned int span_offset; - - unsigned long fb_offset; - unsigned long mmio_offset; - unsigned long ring_offset; - unsigned long ring_rptr_offset; - unsigned long buffers_offset; - unsigned long agp_textures_offset; -} drm_r128_init_t; - -typedef struct drm_r128_cce_stop { - int flush; - int idle; -} drm_r128_cce_stop_t; - -typedef struct drm_r128_clear { - unsigned int flags; - unsigned int clear_color; - unsigned int clear_depth; - unsigned int color_mask; - unsigned int depth_mask; -} drm_r128_clear_t; - -typedef struct drm_r128_vertex { - int prim; - int idx; /* Index of vertex buffer */ - int count; /* Number of vertices in buffer */ - int discard; /* Client finished with buffer? */ -} drm_r128_vertex_t; - -typedef struct drm_r128_indices { - int prim; - int idx; - int start; - int end; - int discard; /* Client finished with buffer? */ -} drm_r128_indices_t; - -typedef struct drm_r128_blit { - int idx; - int pitch; - int offset; - int format; - unsigned short x, y; - unsigned short width, height; -} drm_r128_blit_t; - -typedef struct drm_r128_depth { - enum { - R128_WRITE_SPAN = 0x01, - R128_WRITE_PIXELS = 0x02, - R128_READ_SPAN = 0x03, - R128_READ_PIXELS = 0x04 - } func; - int n; - int __user *x; - int __user *y; - unsigned int __user *buffer; - unsigned char __user *mask; -} drm_r128_depth_t; - -typedef struct drm_r128_stipple { - unsigned int __user *mask; -} drm_r128_stipple_t; - -typedef struct drm_r128_indirect { - int idx; - int start; - int end; - int discard; -} drm_r128_indirect_t; - -typedef struct drm_r128_fullscreen { - enum { - R128_INIT_FULLSCREEN = 0x01, - R128_CLEANUP_FULLSCREEN = 0x02 - } func; -} drm_r128_fullscreen_t; - -/* 2.3: An ioctl to get parameters that aren't available to the 3d - * client any other way. - */ -#define R128_PARAM_IRQ_NR 1 - -typedef struct drm_r128_getparam { - int param; - void __user *value; -} drm_r128_getparam_t; - -#if defined(__cplusplus) -} -#endif - -#endif -- cgit v1.2.3 From 7872bc2cb13e4dd83d193d50a835e179f449ab07 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Sat, 3 Dec 2022 18:22:55 +0800 Subject: drm: Remove the obsolete driver-savage Commit 399516ab0fee ("MAINTAINERS: Add a bunch of legacy (UMS) DRM drivers") marked savage driver obsolete 7 years ago. And the mesa UMD of this drm driver already in deprecated list in the link: https://docs.mesa3d.org/systems.html S3 Savage-->drivers/gpu/drm/savage It's time to remove this driver. Signed-off-by: Cai Huoqing Acked-by: Daniel Vetter Acked-by: Dave Airlie Acked-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20221203102502.3185-5-cai.huoqing@linux.dev --- drivers/gpu/drm/Kconfig | 7 - drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/savage/Makefile | 9 - drivers/gpu/drm/savage/savage_bci.c | 1082 ------------------------------ drivers/gpu/drm/savage/savage_drv.c | 91 --- drivers/gpu/drm/savage/savage_drv.h | 580 ---------------- drivers/gpu/drm/savage/savage_state.c | 1169 --------------------------------- include/uapi/drm/savage_drm.h | 220 ------- 8 files changed, 3159 deletions(-) delete mode 100644 drivers/gpu/drm/savage/Makefile delete mode 100644 drivers/gpu/drm/savage/savage_bci.c delete mode 100644 drivers/gpu/drm/savage/savage_drv.c delete mode 100644 drivers/gpu/drm/savage/savage_drv.h delete mode 100644 drivers/gpu/drm/savage/savage_state.c delete mode 100644 include/uapi/drm/savage_drm.h (limited to 'include') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index d54bb7795330..14520cd4f7c0 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -421,13 +421,6 @@ config DRM_VIA Choose this option if you have a Via unichrome or compatible video chipset. If M is selected the module will be called via. -config DRM_SAVAGE - tristate "Savage video cards" - depends on DRM && PCI - help - Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister - chipset. If M is selected the module will be called savage. - endif # DRM_LEGACY config DRM_EXPORT_FOR_TESTS diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 76f8d567502a..dcc4801832ee 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -142,7 +142,6 @@ obj-$(CONFIG_DRM_MGAG200) += mgag200/ obj-$(CONFIG_DRM_V3D) += v3d/ obj-$(CONFIG_DRM_VC4) += vc4/ obj-$(CONFIG_DRM_SIS) += sis/ -obj-$(CONFIG_DRM_SAVAGE)+= savage/ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/ obj-$(CONFIG_DRM_VIA) +=via/ obj-$(CONFIG_DRM_VGEM) += vgem/ diff --git a/drivers/gpu/drm/savage/Makefile b/drivers/gpu/drm/savage/Makefile deleted file mode 100644 index 3e520763d259..000000000000 --- a/drivers/gpu/drm/savage/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the drm device driver. This driver provides support for the -# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. - -savage-y := savage_drv.o savage_bci.o savage_state.o - -obj-$(CONFIG_DRM_SAVAGE)+= savage.o - diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c deleted file mode 100644 index e33385dfe3ed..000000000000 --- a/drivers/gpu/drm/savage/savage_bci.c +++ /dev/null @@ -1,1082 +0,0 @@ -/* savage_bci.c -- BCI support for Savage - * - * Copyright 2004 Felix Kuehling - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "savage_drv.h" - -/* Need a long timeout for shadow status updates can take a while - * and so can waiting for events when the queue is full. */ -#define SAVAGE_DEFAULT_USEC_TIMEOUT 1000000 /* 1s */ -#define SAVAGE_EVENT_USEC_TIMEOUT 5000000 /* 5s */ -#define SAVAGE_FREELIST_DEBUG 0 - -static int savage_do_cleanup_bci(struct drm_device *dev); - -static int -savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n) -{ - uint32_t mask = dev_priv->status_used_mask; - uint32_t threshold = dev_priv->bci_threshold_hi; - uint32_t status; - int i; - -#if SAVAGE_BCI_DEBUG - if (n > dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - threshold) - DRM_ERROR("Trying to emit %d words " - "(more than guaranteed space in COB)\n", n); -#endif - - for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) { - mb(); - status = dev_priv->status_ptr[0]; - if ((status & mask) < threshold) - return 0; - udelay(1); - } - -#if SAVAGE_BCI_DEBUG - DRM_ERROR("failed!\n"); - DRM_INFO(" status=0x%08x, threshold=0x%08x\n", status, threshold); -#endif - return -EBUSY; -} - -static int -savage_bci_wait_fifo_s3d(drm_savage_private_t * dev_priv, unsigned int n) -{ - uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n; - uint32_t status; - int i; - - for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) { - status = SAVAGE_READ(SAVAGE_STATUS_WORD0); - if ((status & SAVAGE_FIFO_USED_MASK_S3D) <= maxUsed) - return 0; - udelay(1); - } - -#if SAVAGE_BCI_DEBUG - DRM_ERROR("failed!\n"); - DRM_INFO(" status=0x%08x\n", status); -#endif - return -EBUSY; -} - -static int -savage_bci_wait_fifo_s4(drm_savage_private_t * dev_priv, unsigned int n) -{ - uint32_t maxUsed = dev_priv->cob_size + SAVAGE_BCI_FIFO_SIZE - n; - uint32_t status; - int i; - - for (i = 0; i < SAVAGE_DEFAULT_USEC_TIMEOUT; i++) { - status = SAVAGE_READ(SAVAGE_ALT_STATUS_WORD0); - if ((status & SAVAGE_FIFO_USED_MASK_S4) <= maxUsed) - return 0; - udelay(1); - } - -#if SAVAGE_BCI_DEBUG - DRM_ERROR("failed!\n"); - DRM_INFO(" status=0x%08x\n", status); -#endif - return -EBUSY; -} - -/* - * Waiting for events. - * - * The BIOSresets the event tag to 0 on mode changes. Therefore we - * never emit 0 to the event tag. If we find a 0 event tag we know the - * BIOS stomped on it and return success assuming that the BIOS waited - * for engine idle. - * - * Note: if the Xserver uses the event tag it has to follow the same - * rule. Otherwise there may be glitches every 2^16 events. - */ -static int -savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e) -{ - uint32_t status; - int i; - - for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) { - mb(); - status = dev_priv->status_ptr[1]; - if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff || - (status & 0xffff) == 0) - return 0; - udelay(1); - } - -#if SAVAGE_BCI_DEBUG - DRM_ERROR("failed!\n"); - DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e); -#endif - - return -EBUSY; -} - -static int -savage_bci_wait_event_reg(drm_savage_private_t * dev_priv, uint16_t e) -{ - uint32_t status; - int i; - - for (i = 0; i < SAVAGE_EVENT_USEC_TIMEOUT; i++) { - status = SAVAGE_READ(SAVAGE_STATUS_WORD1); - if ((((status & 0xffff) - e) & 0xffff) <= 0x7fff || - (status & 0xffff) == 0) - return 0; - udelay(1); - } - -#if SAVAGE_BCI_DEBUG - DRM_ERROR("failed!\n"); - DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e); -#endif - - return -EBUSY; -} - -uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv, - unsigned int flags) -{ - uint16_t count; - BCI_LOCALS; - - if (dev_priv->status_ptr) { - /* coordinate with Xserver */ - count = dev_priv->status_ptr[1023]; - if (count < dev_priv->event_counter) - dev_priv->event_wrap++; - } else { - count = dev_priv->event_counter; - } - count = (count + 1) & 0xffff; - if (count == 0) { - count++; /* See the comment above savage_wait_event_*. */ - dev_priv->event_wrap++; - } - dev_priv->event_counter = count; - if (dev_priv->status_ptr) - dev_priv->status_ptr[1023] = (uint32_t) count; - - if ((flags & (SAVAGE_WAIT_2D | SAVAGE_WAIT_3D))) { - unsigned int wait_cmd = BCI_CMD_WAIT; - if ((flags & SAVAGE_WAIT_2D)) - wait_cmd |= BCI_CMD_WAIT_2D; - if ((flags & SAVAGE_WAIT_3D)) - wait_cmd |= BCI_CMD_WAIT_3D; - BEGIN_BCI(2); - BCI_WRITE(wait_cmd); - } else { - BEGIN_BCI(1); - } - BCI_WRITE(BCI_CMD_UPDATE_EVENT_TAG | (uint32_t) count); - - return count; -} - -/* - * Freelist management - */ -static int savage_freelist_init(struct drm_device * dev) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_savage_buf_priv_t *entry; - int i; - DRM_DEBUG("count=%d\n", dma->buf_count); - - dev_priv->head.next = &dev_priv->tail; - dev_priv->head.prev = NULL; - dev_priv->head.buf = NULL; - - dev_priv->tail.next = NULL; - dev_priv->tail.prev = &dev_priv->head; - dev_priv->tail.buf = NULL; - - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[i]; - entry = buf->dev_private; - - SET_AGE(&entry->age, 0, 0); - entry->buf = buf; - - entry->next = dev_priv->head.next; - entry->prev = &dev_priv->head; - dev_priv->head.next->prev = entry; - dev_priv->head.next = entry; - } - - return 0; -} - -static struct drm_buf *savage_freelist_get(struct drm_device * dev) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - drm_savage_buf_priv_t *tail = dev_priv->tail.prev; - uint16_t event; - unsigned int wrap; - DRM_DEBUG("\n"); - - UPDATE_EVENT_COUNTER(); - if (dev_priv->status_ptr) - event = dev_priv->status_ptr[1] & 0xffff; - else - event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff; - wrap = dev_priv->event_wrap; - if (event > dev_priv->event_counter) - wrap--; /* hardware hasn't passed the last wrap yet */ - - DRM_DEBUG(" tail=0x%04x %d\n", tail->age.event, tail->age.wrap); - DRM_DEBUG(" head=0x%04x %d\n", event, wrap); - - if (tail->buf && (TEST_AGE(&tail->age, event, wrap) || event == 0)) { - drm_savage_buf_priv_t *next = tail->next; - drm_savage_buf_priv_t *prev = tail->prev; - prev->next = next; - next->prev = prev; - tail->next = tail->prev = NULL; - return tail->buf; - } - - DRM_DEBUG("returning NULL, tail->buf=%p!\n", tail->buf); - return NULL; -} - -void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - drm_savage_buf_priv_t *entry = buf->dev_private, *prev, *next; - - DRM_DEBUG("age=0x%04x wrap=%d\n", entry->age.event, entry->age.wrap); - - if (entry->next != NULL || entry->prev != NULL) { - DRM_ERROR("entry already on freelist.\n"); - return; - } - - prev = &dev_priv->head; - next = prev->next; - prev->next = entry; - next->prev = entry; - entry->prev = prev; - entry->next = next; -} - -/* - * Command DMA - */ -static int savage_dma_init(drm_savage_private_t * dev_priv) -{ - unsigned int i; - - dev_priv->nr_dma_pages = dev_priv->cmd_dma->size / - (SAVAGE_DMA_PAGE_SIZE * 4); - dev_priv->dma_pages = kmalloc_array(dev_priv->nr_dma_pages, - sizeof(drm_savage_dma_page_t), - GFP_KERNEL); - if (dev_priv->dma_pages == NULL) - return -ENOMEM; - - for (i = 0; i < dev_priv->nr_dma_pages; ++i) { - SET_AGE(&dev_priv->dma_pages[i].age, 0, 0); - dev_priv->dma_pages[i].used = 0; - dev_priv->dma_pages[i].flushed = 0; - } - SET_AGE(&dev_priv->last_dma_age, 0, 0); - - dev_priv->first_dma_page = 0; - dev_priv->current_dma_page = 0; - - return 0; -} - -void savage_dma_reset(drm_savage_private_t * dev_priv) -{ - uint16_t event; - unsigned int wrap, i; - event = savage_bci_emit_event(dev_priv, 0); - wrap = dev_priv->event_wrap; - for (i = 0; i < dev_priv->nr_dma_pages; ++i) { - SET_AGE(&dev_priv->dma_pages[i].age, event, wrap); - dev_priv->dma_pages[i].used = 0; - dev_priv->dma_pages[i].flushed = 0; - } - SET_AGE(&dev_priv->last_dma_age, event, wrap); - dev_priv->first_dma_page = dev_priv->current_dma_page = 0; -} - -void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page) -{ - uint16_t event; - unsigned int wrap; - - /* Faked DMA buffer pages don't age. */ - if (dev_priv->cmd_dma == &dev_priv->fake_dma) - return; - - UPDATE_EVENT_COUNTER(); - if (dev_priv->status_ptr) - event = dev_priv->status_ptr[1] & 0xffff; - else - event = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff; - wrap = dev_priv->event_wrap; - if (event > dev_priv->event_counter) - wrap--; /* hardware hasn't passed the last wrap yet */ - - if (dev_priv->dma_pages[page].age.wrap > wrap || - (dev_priv->dma_pages[page].age.wrap == wrap && - dev_priv->dma_pages[page].age.event > event)) { - if (dev_priv->wait_evnt(dev_priv, - dev_priv->dma_pages[page].age.event) - < 0) - DRM_ERROR("wait_evnt failed!\n"); - } -} - -uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv, unsigned int n) -{ - unsigned int cur = dev_priv->current_dma_page; - unsigned int rest = SAVAGE_DMA_PAGE_SIZE - - dev_priv->dma_pages[cur].used; - unsigned int nr_pages = (n - rest + SAVAGE_DMA_PAGE_SIZE - 1) / - SAVAGE_DMA_PAGE_SIZE; - uint32_t *dma_ptr; - unsigned int i; - - DRM_DEBUG("cur=%u, cur->used=%u, n=%u, rest=%u, nr_pages=%u\n", - cur, dev_priv->dma_pages[cur].used, n, rest, nr_pages); - - if (cur + nr_pages < dev_priv->nr_dma_pages) { - dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle + - cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used; - if (n < rest) - rest = n; - dev_priv->dma_pages[cur].used += rest; - n -= rest; - cur++; - } else { - dev_priv->dma_flush(dev_priv); - nr_pages = - (n + SAVAGE_DMA_PAGE_SIZE - 1) / SAVAGE_DMA_PAGE_SIZE; - for (i = cur; i < dev_priv->nr_dma_pages; ++i) { - dev_priv->dma_pages[i].age = dev_priv->last_dma_age; - dev_priv->dma_pages[i].used = 0; - dev_priv->dma_pages[i].flushed = 0; - } - dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle; - dev_priv->first_dma_page = cur = 0; - } - for (i = cur; nr_pages > 0; ++i, --nr_pages) { -#if SAVAGE_DMA_DEBUG - if (dev_priv->dma_pages[i].used) { - DRM_ERROR("unflushed page %u: used=%u\n", - i, dev_priv->dma_pages[i].used); - } -#endif - if (n > SAVAGE_DMA_PAGE_SIZE) - dev_priv->dma_pages[i].used = SAVAGE_DMA_PAGE_SIZE; - else - dev_priv->dma_pages[i].used = n; - n -= SAVAGE_DMA_PAGE_SIZE; - } - dev_priv->current_dma_page = --i; - - DRM_DEBUG("cur=%u, cur->used=%u, n=%u\n", - i, dev_priv->dma_pages[i].used, n); - - savage_dma_wait(dev_priv, dev_priv->current_dma_page); - - return dma_ptr; -} - -static void savage_dma_flush(drm_savage_private_t * dev_priv) -{ - unsigned int first = dev_priv->first_dma_page; - unsigned int cur = dev_priv->current_dma_page; - uint16_t event; - unsigned int wrap, pad, align, len, i; - unsigned long phys_addr; - BCI_LOCALS; - - if (first == cur && - dev_priv->dma_pages[cur].used == dev_priv->dma_pages[cur].flushed) - return; - - /* pad length to multiples of 2 entries - * align start of next DMA block to multiles of 8 entries */ - pad = -dev_priv->dma_pages[cur].used & 1; - align = -(dev_priv->dma_pages[cur].used + pad) & 7; - - DRM_DEBUG("first=%u, cur=%u, first->flushed=%u, cur->used=%u, " - "pad=%u, align=%u\n", - first, cur, dev_priv->dma_pages[first].flushed, - dev_priv->dma_pages[cur].used, pad, align); - - /* pad with noops */ - if (pad) { - uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle + - cur * SAVAGE_DMA_PAGE_SIZE + dev_priv->dma_pages[cur].used; - dev_priv->dma_pages[cur].used += pad; - while (pad != 0) { - *dma_ptr++ = BCI_CMD_WAIT; - pad--; - } - } - - mb(); - - /* do flush ... */ - phys_addr = dev_priv->cmd_dma->offset + - (first * SAVAGE_DMA_PAGE_SIZE + - dev_priv->dma_pages[first].flushed) * 4; - len = (cur - first) * SAVAGE_DMA_PAGE_SIZE + - dev_priv->dma_pages[cur].used - dev_priv->dma_pages[first].flushed; - - DRM_DEBUG("phys_addr=%lx, len=%u\n", - phys_addr | dev_priv->dma_type, len); - - BEGIN_BCI(3); - BCI_SET_REGISTERS(SAVAGE_DMABUFADDR, 1); - BCI_WRITE(phys_addr | dev_priv->dma_type); - BCI_DMA(len); - - /* fix alignment of the start of the next block */ - dev_priv->dma_pages[cur].used += align; - - /* age DMA pages */ - event = savage_bci_emit_event(dev_priv, 0); - wrap = dev_priv->event_wrap; - for (i = first; i < cur; ++i) { - SET_AGE(&dev_priv->dma_pages[i].age, event, wrap); - dev_priv->dma_pages[i].used = 0; - dev_priv->dma_pages[i].flushed = 0; - } - /* age the current page only when it's full */ - if (dev_priv->dma_pages[cur].used == SAVAGE_DMA_PAGE_SIZE) { - SET_AGE(&dev_priv->dma_pages[cur].age, event, wrap); - dev_priv->dma_pages[cur].used = 0; - dev_priv->dma_pages[cur].flushed = 0; - /* advance to next page */ - cur++; - if (cur == dev_priv->nr_dma_pages) - cur = 0; - dev_priv->first_dma_page = dev_priv->current_dma_page = cur; - } else { - dev_priv->first_dma_page = cur; - dev_priv->dma_pages[cur].flushed = dev_priv->dma_pages[i].used; - } - SET_AGE(&dev_priv->last_dma_age, event, wrap); - - DRM_DEBUG("first=cur=%u, cur->used=%u, cur->flushed=%u\n", cur, - dev_priv->dma_pages[cur].used, - dev_priv->dma_pages[cur].flushed); -} - -static void savage_fake_dma_flush(drm_savage_private_t * dev_priv) -{ - unsigned int i, j; - BCI_LOCALS; - - if (dev_priv->first_dma_page == dev_priv->current_dma_page && - dev_priv->dma_pages[dev_priv->current_dma_page].used == 0) - return; - - DRM_DEBUG("first=%u, cur=%u, cur->used=%u\n", - dev_priv->first_dma_page, dev_priv->current_dma_page, - dev_priv->dma_pages[dev_priv->current_dma_page].used); - - for (i = dev_priv->first_dma_page; - i <= dev_priv->current_dma_page && dev_priv->dma_pages[i].used; - ++i) { - uint32_t *dma_ptr = (uint32_t *) dev_priv->cmd_dma->handle + - i * SAVAGE_DMA_PAGE_SIZE; -#if SAVAGE_DMA_DEBUG - /* Sanity check: all pages except the last one must be full. */ - if (i < dev_priv->current_dma_page && - dev_priv->dma_pages[i].used != SAVAGE_DMA_PAGE_SIZE) { - DRM_ERROR("partial DMA page %u: used=%u", - i, dev_priv->dma_pages[i].used); - } -#endif - BEGIN_BCI(dev_priv->dma_pages[i].used); - for (j = 0; j < dev_priv->dma_pages[i].used; ++j) { - BCI_WRITE(dma_ptr[j]); - } - dev_priv->dma_pages[i].used = 0; - } - - /* reset to first page */ - dev_priv->first_dma_page = dev_priv->current_dma_page = 0; -} - -int savage_driver_load(struct drm_device *dev, unsigned long chipset) -{ - struct pci_dev *pdev = to_pci_dev(dev->dev); - drm_savage_private_t *dev_priv; - - dev_priv = kzalloc(sizeof(drm_savage_private_t), GFP_KERNEL); - if (dev_priv == NULL) - return -ENOMEM; - - dev->dev_private = (void *)dev_priv; - - dev_priv->chipset = (enum savage_family)chipset; - - pci_set_master(pdev); - - return 0; -} - - -/* - * Initialize mappings. On Savage4 and SavageIX the alignment - * and size of the aperture is not suitable for automatic MTRR setup - * in drm_legacy_addmap. Therefore we add them manually before the maps are - * initialized, and tear them down on last close. - */ -int savage_driver_firstopen(struct drm_device *dev) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - struct pci_dev *pdev = to_pci_dev(dev->dev); - unsigned long mmio_base, fb_base, fb_size, aperture_base; - int ret = 0; - - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - fb_base = pci_resource_start(pdev, 0); - fb_size = SAVAGE_FB_SIZE_S3; - mmio_base = fb_base + SAVAGE_FB_SIZE_S3; - aperture_base = fb_base + SAVAGE_APERTURE_OFFSET; - /* this should always be true */ - if (pci_resource_len(pdev, 0) == 0x08000000) { - /* Don't make MMIO write-cobining! We need 3 - * MTRRs. */ - dev_priv->mtrr_handles[0] = - arch_phys_wc_add(fb_base, 0x01000000); - dev_priv->mtrr_handles[1] = - arch_phys_wc_add(fb_base + 0x02000000, - 0x02000000); - dev_priv->mtrr_handles[2] = - arch_phys_wc_add(fb_base + 0x04000000, - 0x04000000); - } else { - DRM_ERROR("strange pci_resource_len %08llx\n", - (unsigned long long) - pci_resource_len(pdev, 0)); - } - } else if (dev_priv->chipset != S3_SUPERSAVAGE && - dev_priv->chipset != S3_SAVAGE2000) { - mmio_base = pci_resource_start(pdev, 0); - fb_base = pci_resource_start(pdev, 1); - fb_size = SAVAGE_FB_SIZE_S4; - aperture_base = fb_base + SAVAGE_APERTURE_OFFSET; - /* this should always be true */ - if (pci_resource_len(pdev, 1) == 0x08000000) { - /* Can use one MTRR to cover both fb and - * aperture. */ - dev_priv->mtrr_handles[0] = - arch_phys_wc_add(fb_base, - 0x08000000); - } else { - DRM_ERROR("strange pci_resource_len %08llx\n", - (unsigned long long) - pci_resource_len(pdev, 1)); - } - } else { - mmio_base = pci_resource_start(pdev, 0); - fb_base = pci_resource_start(pdev, 1); - fb_size = pci_resource_len(pdev, 1); - aperture_base = pci_resource_start(pdev, 2); - /* Automatic MTRR setup will do the right thing. */ - } - - ret = drm_legacy_addmap(dev, mmio_base, SAVAGE_MMIO_SIZE, - _DRM_REGISTERS, _DRM_READ_ONLY, - &dev_priv->mmio); - if (ret) - return ret; - - ret = drm_legacy_addmap(dev, fb_base, fb_size, _DRM_FRAME_BUFFER, - _DRM_WRITE_COMBINING, &dev_priv->fb); - if (ret) - return ret; - - ret = drm_legacy_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE, - _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, - &dev_priv->aperture); - return ret; -} - -/* - * Delete MTRRs and free device-private data. - */ -void savage_driver_lastclose(struct drm_device *dev) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - int i; - - for (i = 0; i < 3; ++i) { - arch_phys_wc_del(dev_priv->mtrr_handles[i]); - dev_priv->mtrr_handles[i] = 0; - } -} - -void savage_driver_unload(struct drm_device *dev) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - - kfree(dev_priv); -} - -static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - - if (init->fb_bpp != 16 && init->fb_bpp != 32) { - DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp); - return -EINVAL; - } - if (init->depth_bpp != 16 && init->depth_bpp != 32) { - DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp); - return -EINVAL; - } - if (init->dma_type != SAVAGE_DMA_AGP && - init->dma_type != SAVAGE_DMA_PCI) { - DRM_ERROR("invalid dma memory type %d!\n", init->dma_type); - return -EINVAL; - } - - dev_priv->cob_size = init->cob_size; - dev_priv->bci_threshold_lo = init->bci_threshold_lo; - dev_priv->bci_threshold_hi = init->bci_threshold_hi; - dev_priv->dma_type = init->dma_type; - - dev_priv->fb_bpp = init->fb_bpp; - dev_priv->front_offset = init->front_offset; - dev_priv->front_pitch = init->front_pitch; - dev_priv->back_offset = init->back_offset; - dev_priv->back_pitch = init->back_pitch; - dev_priv->depth_bpp = init->depth_bpp; - dev_priv->depth_offset = init->depth_offset; - dev_priv->depth_pitch = init->depth_pitch; - - dev_priv->texture_offset = init->texture_offset; - dev_priv->texture_size = init->texture_size; - - dev_priv->sarea = drm_legacy_getsarea(dev); - if (!dev_priv->sarea) { - DRM_ERROR("could not find sarea!\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - if (init->status_offset != 0) { - dev_priv->status = drm_legacy_findmap(dev, init->status_offset); - if (!dev_priv->status) { - DRM_ERROR("could not find shadow status region!\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - } else { - dev_priv->status = NULL; - } - if (dev_priv->dma_type == SAVAGE_DMA_AGP && init->buffers_offset) { - dev->agp_buffer_token = init->buffers_offset; - dev->agp_buffer_map = drm_legacy_findmap(dev, - init->buffers_offset); - if (!dev->agp_buffer_map) { - DRM_ERROR("could not find DMA buffer region!\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - drm_legacy_ioremap(dev->agp_buffer_map, dev); - if (!dev->agp_buffer_map->handle) { - DRM_ERROR("failed to ioremap DMA buffer region!\n"); - savage_do_cleanup_bci(dev); - return -ENOMEM; - } - } - if (init->agp_textures_offset) { - dev_priv->agp_textures = - drm_legacy_findmap(dev, init->agp_textures_offset); - if (!dev_priv->agp_textures) { - DRM_ERROR("could not find agp texture region!\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - } else { - dev_priv->agp_textures = NULL; - } - - if (init->cmd_dma_offset) { - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - DRM_ERROR("command DMA not supported on " - "Savage3D/MX/IX.\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - if (dev->dma && dev->dma->buflist) { - DRM_ERROR("command and vertex DMA not supported " - "at the same time.\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - dev_priv->cmd_dma = drm_legacy_findmap(dev, init->cmd_dma_offset); - if (!dev_priv->cmd_dma) { - DRM_ERROR("could not find command DMA region!\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - if (dev_priv->dma_type == SAVAGE_DMA_AGP) { - if (dev_priv->cmd_dma->type != _DRM_AGP) { - DRM_ERROR("AGP command DMA region is not a " - "_DRM_AGP map!\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - drm_legacy_ioremap(dev_priv->cmd_dma, dev); - if (!dev_priv->cmd_dma->handle) { - DRM_ERROR("failed to ioremap command " - "DMA region!\n"); - savage_do_cleanup_bci(dev); - return -ENOMEM; - } - } else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) { - DRM_ERROR("PCI command DMA region is not a " - "_DRM_CONSISTENT map!\n"); - savage_do_cleanup_bci(dev); - return -EINVAL; - } - } else { - dev_priv->cmd_dma = NULL; - } - - dev_priv->dma_flush = savage_dma_flush; - if (!dev_priv->cmd_dma) { - DRM_DEBUG("falling back to faked command DMA.\n"); - dev_priv->fake_dma.offset = 0; - dev_priv->fake_dma.size = SAVAGE_FAKE_DMA_SIZE; - dev_priv->fake_dma.type = _DRM_SHM; - dev_priv->fake_dma.handle = kmalloc(SAVAGE_FAKE_DMA_SIZE, - GFP_KERNEL); - if (!dev_priv->fake_dma.handle) { - DRM_ERROR("could not allocate faked DMA buffer!\n"); - savage_do_cleanup_bci(dev); - return -ENOMEM; - } - dev_priv->cmd_dma = &dev_priv->fake_dma; - dev_priv->dma_flush = savage_fake_dma_flush; - } - - dev_priv->sarea_priv = - (drm_savage_sarea_t *) ((uint8_t *) dev_priv->sarea->handle + - init->sarea_priv_offset); - - /* setup bitmap descriptors */ - { - unsigned int color_tile_format; - unsigned int depth_tile_format; - unsigned int front_stride, back_stride, depth_stride; - if (dev_priv->chipset <= S3_SAVAGE4) { - color_tile_format = dev_priv->fb_bpp == 16 ? - SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP; - depth_tile_format = dev_priv->depth_bpp == 16 ? - SAVAGE_BD_TILE_16BPP : SAVAGE_BD_TILE_32BPP; - } else { - color_tile_format = SAVAGE_BD_TILE_DEST; - depth_tile_format = SAVAGE_BD_TILE_DEST; - } - front_stride = dev_priv->front_pitch / (dev_priv->fb_bpp / 8); - back_stride = dev_priv->back_pitch / (dev_priv->fb_bpp / 8); - depth_stride = - dev_priv->depth_pitch / (dev_priv->depth_bpp / 8); - - dev_priv->front_bd = front_stride | SAVAGE_BD_BW_DISABLE | - (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) | - (color_tile_format << SAVAGE_BD_TILE_SHIFT); - - dev_priv->back_bd = back_stride | SAVAGE_BD_BW_DISABLE | - (dev_priv->fb_bpp << SAVAGE_BD_BPP_SHIFT) | - (color_tile_format << SAVAGE_BD_TILE_SHIFT); - - dev_priv->depth_bd = depth_stride | SAVAGE_BD_BW_DISABLE | - (dev_priv->depth_bpp << SAVAGE_BD_BPP_SHIFT) | - (depth_tile_format << SAVAGE_BD_TILE_SHIFT); - } - - /* setup status and bci ptr */ - dev_priv->event_counter = 0; - dev_priv->event_wrap = 0; - dev_priv->bci_ptr = (volatile uint32_t *) - ((uint8_t *) dev_priv->mmio->handle + SAVAGE_BCI_OFFSET); - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S3D; - } else { - dev_priv->status_used_mask = SAVAGE_FIFO_USED_MASK_S4; - } - if (dev_priv->status != NULL) { - dev_priv->status_ptr = - (volatile uint32_t *)dev_priv->status->handle; - dev_priv->wait_fifo = savage_bci_wait_fifo_shadow; - dev_priv->wait_evnt = savage_bci_wait_event_shadow; - dev_priv->status_ptr[1023] = dev_priv->event_counter; - } else { - dev_priv->status_ptr = NULL; - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - dev_priv->wait_fifo = savage_bci_wait_fifo_s3d; - } else { - dev_priv->wait_fifo = savage_bci_wait_fifo_s4; - } - dev_priv->wait_evnt = savage_bci_wait_event_reg; - } - - /* cliprect functions */ - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) - dev_priv->emit_clip_rect = savage_emit_clip_rect_s3d; - else - dev_priv->emit_clip_rect = savage_emit_clip_rect_s4; - - if (savage_freelist_init(dev) < 0) { - DRM_ERROR("could not initialize freelist\n"); - savage_do_cleanup_bci(dev); - return -ENOMEM; - } - - if (savage_dma_init(dev_priv) < 0) { - DRM_ERROR("could not initialize command DMA\n"); - savage_do_cleanup_bci(dev); - return -ENOMEM; - } - - return 0; -} - -static int savage_do_cleanup_bci(struct drm_device * dev) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - - if (dev_priv->cmd_dma == &dev_priv->fake_dma) { - kfree(dev_priv->fake_dma.handle); - } else if (dev_priv->cmd_dma && dev_priv->cmd_dma->handle && - dev_priv->cmd_dma->type == _DRM_AGP && - dev_priv->dma_type == SAVAGE_DMA_AGP) - drm_legacy_ioremapfree(dev_priv->cmd_dma, dev); - - if (dev_priv->dma_type == SAVAGE_DMA_AGP && - dev->agp_buffer_map && dev->agp_buffer_map->handle) { - drm_legacy_ioremapfree(dev->agp_buffer_map, dev); - /* make sure the next instance (which may be running - * in PCI mode) doesn't try to use an old - * agp_buffer_map. */ - dev->agp_buffer_map = NULL; - } - - kfree(dev_priv->dma_pages); - - return 0; -} - -static int savage_bci_init(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_savage_init_t *init = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - switch (init->func) { - case SAVAGE_INIT_BCI: - return savage_do_init_bci(dev, init); - case SAVAGE_CLEANUP_BCI: - return savage_do_cleanup_bci(dev); - } - - return -EINVAL; -} - -static int savage_bci_event_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - drm_savage_event_emit_t *event = data; - - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - event->count = savage_bci_emit_event(dev_priv, event->flags); - event->count |= dev_priv->event_wrap << 16; - - return 0; -} - -static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - drm_savage_event_wait_t *event = data; - unsigned int event_e, hw_e; - unsigned int event_w, hw_w; - - DRM_DEBUG("\n"); - - UPDATE_EVENT_COUNTER(); - if (dev_priv->status_ptr) - hw_e = dev_priv->status_ptr[1] & 0xffff; - else - hw_e = SAVAGE_READ(SAVAGE_STATUS_WORD1) & 0xffff; - hw_w = dev_priv->event_wrap; - if (hw_e > dev_priv->event_counter) - hw_w--; /* hardware hasn't passed the last wrap yet */ - - event_e = event->count & 0xffff; - event_w = event->count >> 16; - - /* Don't need to wait if - * - event counter wrapped since the event was emitted or - * - the hardware has advanced up to or over the event to wait for. - */ - if (event_w < hw_w || (event_w == hw_w && event_e <= hw_e)) - return 0; - else - return dev_priv->wait_evnt(dev_priv, event_e); -} - -/* - * DMA buffer management - */ - -static int savage_bci_get_buffers(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_dma *d) -{ - struct drm_buf *buf; - int i; - - for (i = d->granted_count; i < d->request_count; i++) { - buf = savage_freelist_get(dev); - if (!buf) - return -EAGAIN; - - buf->file_priv = file_priv; - - if (copy_to_user(&d->request_indices[i], - &buf->idx, sizeof(buf->idx))) - return -EFAULT; - if (copy_to_user(&d->request_sizes[i], - &buf->total, sizeof(buf->total))) - return -EFAULT; - - d->granted_count++; - } - return 0; -} - -int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - struct drm_dma *d = data; - int ret = 0; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - /* Please don't send us buffers. - */ - if (d->send_count != 0) { - DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - task_pid_nr(current), d->send_count); - return -EINVAL; - } - - /* We'll send you buffers. - */ - if (d->request_count < 0 || d->request_count > dma->buf_count) { - DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - task_pid_nr(current), d->request_count, dma->buf_count); - return -EINVAL; - } - - d->granted_count = 0; - - if (d->request_count) { - ret = savage_bci_get_buffers(dev, file_priv, d); - } - - return ret; -} - -void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - drm_savage_private_t *dev_priv = dev->dev_private; - int release_idlelock = 0; - int i; - - if (!dma) - return; - if (!dev_priv) - return; - if (!dma->buflist) - return; - - if (file_priv->master && file_priv->master->lock.hw_lock) { - drm_legacy_idlelock_take(&file_priv->master->lock); - release_idlelock = 1; - } - - for (i = 0; i < dma->buf_count; i++) { - struct drm_buf *buf = dma->buflist[i]; - drm_savage_buf_priv_t *buf_priv = buf->dev_private; - - if (buf->file_priv == file_priv && buf_priv && - buf_priv->next == NULL && buf_priv->prev == NULL) { - uint16_t event; - DRM_DEBUG("reclaimed from client\n"); - event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D); - SET_AGE(&buf_priv->age, event, dev_priv->event_wrap); - savage_freelist_put(dev, buf); - } - } - - if (release_idlelock) - drm_legacy_idlelock_release(&file_priv->master->lock); -} - -const struct drm_ioctl_desc savage_ioctls[] = { - DRM_IOCTL_DEF_DRV(SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH), - DRM_IOCTL_DEF_DRV(SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH), - DRM_IOCTL_DEF_DRV(SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH), -}; - -int savage_max_ioctl = ARRAY_SIZE(savage_ioctls); diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c deleted file mode 100644 index 799bd11adb9c..000000000000 --- a/drivers/gpu/drm/savage/savage_drv.c +++ /dev/null @@ -1,91 +0,0 @@ -/* savage_drv.c -- Savage driver for Linux - * - * Copyright 2004 Felix Kuehling - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include - -#include -#include -#include - -#include "savage_drv.h" - -static struct pci_device_id pciidlist[] = { - savage_PCI_IDS -}; - -static const struct file_operations savage_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = drm_legacy_mmap, - .poll = drm_poll, - .compat_ioctl = drm_compat_ioctl, - .llseek = noop_llseek, -}; - -static struct drm_driver driver = { - .driver_features = - DRIVER_USE_AGP | DRIVER_HAVE_DMA | DRIVER_PCI_DMA | DRIVER_LEGACY, - .dev_priv_size = sizeof(drm_savage_buf_priv_t), - .load = savage_driver_load, - .firstopen = savage_driver_firstopen, - .preclose = savage_reclaim_buffers, - .lastclose = savage_driver_lastclose, - .unload = savage_driver_unload, - .ioctls = savage_ioctls, - .dma_ioctl = savage_bci_buffers, - .fops = &savage_driver_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; - -static struct pci_driver savage_pci_driver = { - .name = DRIVER_NAME, - .id_table = pciidlist, -}; - -static int __init savage_init(void) -{ - driver.num_ioctls = savage_max_ioctl; - return drm_legacy_pci_init(&driver, &savage_pci_driver); -} - -static void __exit savage_exit(void) -{ - drm_legacy_pci_exit(&driver, &savage_pci_driver); -} - -module_init(savage_init); -module_exit(savage_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/savage/savage_drv.h b/drivers/gpu/drm/savage/savage_drv.h deleted file mode 100644 index b0081bb64776..000000000000 --- a/drivers/gpu/drm/savage/savage_drv.h +++ /dev/null @@ -1,580 +0,0 @@ -/* savage_drv.h -- Private header for the savage driver */ -/* - * Copyright 2004 Felix Kuehling - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __SAVAGE_DRV_H__ -#define __SAVAGE_DRV_H__ - -#include - -#include -#include -#include - -#define DRIVER_AUTHOR "Felix Kuehling" - -#define DRIVER_NAME "savage" -#define DRIVER_DESC "Savage3D/MX/IX, Savage4, SuperSavage, Twister, ProSavage[DDR]" -#define DRIVER_DATE "20050313" - -#define DRIVER_MAJOR 2 -#define DRIVER_MINOR 4 -#define DRIVER_PATCHLEVEL 1 -/* Interface history: - * - * 1.x The DRM driver from the VIA/S3 code drop, basically a dummy - * 2.0 The first real DRM - * 2.1 Scissors registers managed by the DRM, 3D operations clipped by - * cliprects of the cmdbuf ioctl - * 2.2 Implemented SAVAGE_CMD_DMA_IDX and SAVAGE_CMD_VB_IDX - * 2.3 Event counters used by BCI_EVENT_EMIT/WAIT ioctls are now 32 bits - * wide and thus very long lived (unlikely to ever wrap). The size - * in the struct was 32 bits before, but only 16 bits were used - * 2.4 Implemented command DMA. Now drm_savage_init_t.cmd_dma_offset is - * actually used - */ - -typedef struct drm_savage_age { - uint16_t event; - unsigned int wrap; -} drm_savage_age_t; - -typedef struct drm_savage_buf_priv { - struct drm_savage_buf_priv *next; - struct drm_savage_buf_priv *prev; - drm_savage_age_t age; - struct drm_buf *buf; -} drm_savage_buf_priv_t; - -typedef struct drm_savage_dma_page { - drm_savage_age_t age; - unsigned int used, flushed; -} drm_savage_dma_page_t; -#define SAVAGE_DMA_PAGE_SIZE 1024 /* in dwords */ -/* Fake DMA buffer size in bytes. 4 pages. Allows a maximum command - * size of 16kbytes or 4k entries. Minimum requirement would be - * 10kbytes for 255 40-byte vertices in one drawing command. */ -#define SAVAGE_FAKE_DMA_SIZE (SAVAGE_DMA_PAGE_SIZE*4*4) - -/* interesting bits of hardware state that are saved in dev_priv */ -typedef union { - struct drm_savage_common_state { - uint32_t vbaddr; - } common; - struct { - unsigned char pad[sizeof(struct drm_savage_common_state)]; - uint32_t texctrl, texaddr; - uint32_t scstart, new_scstart; - uint32_t scend, new_scend; - } s3d; - struct { - unsigned char pad[sizeof(struct drm_savage_common_state)]; - uint32_t texdescr, texaddr0, texaddr1; - uint32_t drawctrl0, new_drawctrl0; - uint32_t drawctrl1, new_drawctrl1; - } s4; -} drm_savage_state_t; - -/* these chip tags should match the ones in the 2D driver in savage_regs.h. */ -enum savage_family { - S3_UNKNOWN = 0, - S3_SAVAGE3D, - S3_SAVAGE_MX, - S3_SAVAGE4, - S3_PROSAVAGE, - S3_TWISTER, - S3_PROSAVAGEDDR, - S3_SUPERSAVAGE, - S3_SAVAGE2000, - S3_LAST -}; - -extern const struct drm_ioctl_desc savage_ioctls[]; -extern int savage_max_ioctl; - -#define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX)) - -#define S3_SAVAGE4_SERIES(chip) ((chip==S3_SAVAGE4) \ - || (chip==S3_PROSAVAGE) \ - || (chip==S3_TWISTER) \ - || (chip==S3_PROSAVAGEDDR)) - -#define S3_SAVAGE_MOBILE_SERIES(chip) ((chip==S3_SAVAGE_MX) || (chip==S3_SUPERSAVAGE)) - -#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) - -#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) \ - ||(chip==S3_PROSAVAGEDDR)) - -/* flags */ -#define SAVAGE_IS_AGP 1 - -typedef struct drm_savage_private { - drm_savage_sarea_t *sarea_priv; - - drm_savage_buf_priv_t head, tail; - - /* who am I? */ - enum savage_family chipset; - - unsigned int cob_size; - unsigned int bci_threshold_lo, bci_threshold_hi; - unsigned int dma_type; - - /* frame buffer layout */ - unsigned int fb_bpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - unsigned int depth_bpp; - unsigned int depth_offset, depth_pitch; - - /* bitmap descriptors for swap and clear */ - unsigned int front_bd, back_bd, depth_bd; - - /* local textures */ - unsigned int texture_offset; - unsigned int texture_size; - - /* memory regions in physical memory */ - drm_local_map_t *sarea; - drm_local_map_t *mmio; - drm_local_map_t *fb; - drm_local_map_t *aperture; - drm_local_map_t *status; - drm_local_map_t *agp_textures; - drm_local_map_t *cmd_dma; - drm_local_map_t fake_dma; - - int mtrr_handles[3]; - - /* BCI and status-related stuff */ - volatile uint32_t *status_ptr, *bci_ptr; - uint32_t status_used_mask; - uint16_t event_counter; - unsigned int event_wrap; - - /* Savage4 command DMA */ - drm_savage_dma_page_t *dma_pages; - unsigned int nr_dma_pages, first_dma_page, current_dma_page; - drm_savage_age_t last_dma_age; - - /* saved hw state for global/local check on S3D */ - uint32_t hw_draw_ctrl, hw_zbuf_ctrl; - /* and for scissors (global, so don't emit if not changed) */ - uint32_t hw_scissors_start, hw_scissors_end; - - drm_savage_state_t state; - - /* after emitting a wait cmd Savage3D needs 63 nops before next DMA */ - unsigned int waiting; - - /* config/hardware-dependent function pointers */ - int (*wait_fifo) (struct drm_savage_private * dev_priv, unsigned int n); - int (*wait_evnt) (struct drm_savage_private * dev_priv, uint16_t e); - /* Err, there is a macro wait_event in include/linux/wait.h. - * Avoid unwanted macro expansion. */ - void (*emit_clip_rect) (struct drm_savage_private * dev_priv, - const struct drm_clip_rect * pbox); - void (*dma_flush) (struct drm_savage_private * dev_priv); -} drm_savage_private_t; - -/* ioctls */ -extern int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); - -/* BCI functions */ -extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv, - unsigned int flags); -extern void savage_freelist_put(struct drm_device * dev, struct drm_buf * buf); -extern void savage_dma_reset(drm_savage_private_t * dev_priv); -extern void savage_dma_wait(drm_savage_private_t * dev_priv, unsigned int page); -extern uint32_t *savage_dma_alloc(drm_savage_private_t * dev_priv, - unsigned int n); -extern int savage_driver_load(struct drm_device *dev, unsigned long chipset); -extern int savage_driver_firstopen(struct drm_device *dev); -extern void savage_driver_lastclose(struct drm_device *dev); -extern void savage_driver_unload(struct drm_device *dev); -extern void savage_reclaim_buffers(struct drm_device *dev, - struct drm_file *file_priv); - -/* state functions */ -extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, - const struct drm_clip_rect * pbox); -extern void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv, - const struct drm_clip_rect * pbox); - -#define SAVAGE_FB_SIZE_S3 0x01000000 /* 16MB */ -#define SAVAGE_FB_SIZE_S4 0x02000000 /* 32MB */ -#define SAVAGE_MMIO_SIZE 0x00080000 /* 512kB */ -#define SAVAGE_APERTURE_OFFSET 0x02000000 /* 32MB */ -#define SAVAGE_APERTURE_SIZE 0x05000000 /* 5 tiled surfaces, 16MB each */ - -#define SAVAGE_BCI_OFFSET 0x00010000 /* offset of the BCI region - * inside the MMIO region */ -#define SAVAGE_BCI_FIFO_SIZE 32 /* number of entries in on-chip - * BCI FIFO */ - -/* - * MMIO registers - */ -#define SAVAGE_STATUS_WORD0 0x48C00 -#define SAVAGE_STATUS_WORD1 0x48C04 -#define SAVAGE_ALT_STATUS_WORD0 0x48C60 - -#define SAVAGE_FIFO_USED_MASK_S3D 0x0001ffff -#define SAVAGE_FIFO_USED_MASK_S4 0x001fffff - -/* Copied from savage_bci.h in the 2D driver with some renaming. */ - -/* Bitmap descriptors */ -#define SAVAGE_BD_STRIDE_SHIFT 0 -#define SAVAGE_BD_BPP_SHIFT 16 -#define SAVAGE_BD_TILE_SHIFT 24 -#define SAVAGE_BD_BW_DISABLE (1<<28) -/* common: */ -#define SAVAGE_BD_TILE_LINEAR 0 -/* savage4, MX, IX, 3D */ -#define SAVAGE_BD_TILE_16BPP 2 -#define SAVAGE_BD_TILE_32BPP 3 -/* twister, prosavage, DDR, supersavage, 2000 */ -#define SAVAGE_BD_TILE_DEST 1 -#define SAVAGE_BD_TILE_TEXTURE 2 -/* GBD - BCI enable */ -/* savage4, MX, IX, 3D */ -#define SAVAGE_GBD_BCI_ENABLE 8 -/* twister, prosavage, DDR, supersavage, 2000 */ -#define SAVAGE_GBD_BCI_ENABLE_TWISTER 0 - -#define SAVAGE_GBD_BIG_ENDIAN 4 -#define SAVAGE_GBD_LITTLE_ENDIAN 0 -#define SAVAGE_GBD_64 1 - -/* Global Bitmap Descriptor */ -#define SAVAGE_BCI_GLB_BD_LOW 0x8168 -#define SAVAGE_BCI_GLB_BD_HIGH 0x816C - -/* - * BCI registers - */ -/* Savage4/Twister/ProSavage 3D registers */ -#define SAVAGE_DRAWLOCALCTRL_S4 0x1e -#define SAVAGE_TEXPALADDR_S4 0x1f -#define SAVAGE_TEXCTRL0_S4 0x20 -#define SAVAGE_TEXCTRL1_S4 0x21 -#define SAVAGE_TEXADDR0_S4 0x22 -#define SAVAGE_TEXADDR1_S4 0x23 -#define SAVAGE_TEXBLEND0_S4 0x24 -#define SAVAGE_TEXBLEND1_S4 0x25 -#define SAVAGE_TEXXPRCLR_S4 0x26 /* never used */ -#define SAVAGE_TEXDESCR_S4 0x27 -#define SAVAGE_FOGTABLE_S4 0x28 -#define SAVAGE_FOGCTRL_S4 0x30 -#define SAVAGE_STENCILCTRL_S4 0x31 -#define SAVAGE_ZBUFCTRL_S4 0x32 -#define SAVAGE_ZBUFOFF_S4 0x33 -#define SAVAGE_DESTCTRL_S4 0x34 -#define SAVAGE_DRAWCTRL0_S4 0x35 -#define SAVAGE_DRAWCTRL1_S4 0x36 -#define SAVAGE_ZWATERMARK_S4 0x37 -#define SAVAGE_DESTTEXRWWATERMARK_S4 0x38 -#define SAVAGE_TEXBLENDCOLOR_S4 0x39 -/* Savage3D/MX/IX 3D registers */ -#define SAVAGE_TEXPALADDR_S3D 0x18 -#define SAVAGE_TEXXPRCLR_S3D 0x19 /* never used */ -#define SAVAGE_TEXADDR_S3D 0x1A -#define SAVAGE_TEXDESCR_S3D 0x1B -#define SAVAGE_TEXCTRL_S3D 0x1C -#define SAVAGE_FOGTABLE_S3D 0x20 -#define SAVAGE_FOGCTRL_S3D 0x30 -#define SAVAGE_DRAWCTRL_S3D 0x31 -#define SAVAGE_ZBUFCTRL_S3D 0x32 -#define SAVAGE_ZBUFOFF_S3D 0x33 -#define SAVAGE_DESTCTRL_S3D 0x34 -#define SAVAGE_SCSTART_S3D 0x35 -#define SAVAGE_SCEND_S3D 0x36 -#define SAVAGE_ZWATERMARK_S3D 0x37 -#define SAVAGE_DESTTEXRWWATERMARK_S3D 0x38 -/* common stuff */ -#define SAVAGE_VERTBUFADDR 0x3e -#define SAVAGE_BITPLANEWTMASK 0xd7 -#define SAVAGE_DMABUFADDR 0x51 - -/* texture enable bits (needed for tex addr checking) */ -#define SAVAGE_TEXCTRL_TEXEN_MASK 0x00010000 /* S3D */ -#define SAVAGE_TEXDESCR_TEX0EN_MASK 0x02000000 /* S4 */ -#define SAVAGE_TEXDESCR_TEX1EN_MASK 0x04000000 /* S4 */ - -/* Global fields in Savage4/Twister/ProSavage 3D registers: - * - * All texture registers and DrawLocalCtrl are local. All other - * registers are global. */ - -/* Global fields in Savage3D/MX/IX 3D registers: - * - * All texture registers are local. DrawCtrl and ZBufCtrl are - * partially local. All other registers are global. - * - * DrawCtrl global fields: cullMode, alphaTestCmpFunc, alphaTestEn, alphaRefVal - * ZBufCtrl global fields: zCmpFunc, zBufEn - */ -#define SAVAGE_DRAWCTRL_S3D_GLOBAL 0x03f3c00c -#define SAVAGE_ZBUFCTRL_S3D_GLOBAL 0x00000027 - -/* Masks for scissor bits (drawCtrl[01] on s4, scissorStart/End on s3d) - */ -#define SAVAGE_SCISSOR_MASK_S4 0x00fff7ff -#define SAVAGE_SCISSOR_MASK_S3D 0x07ff07ff - -/* - * BCI commands - */ -#define BCI_CMD_NOP 0x40000000 -#define BCI_CMD_RECT 0x48000000 -#define BCI_CMD_RECT_XP 0x01000000 -#define BCI_CMD_RECT_YP 0x02000000 -#define BCI_CMD_SCANLINE 0x50000000 -#define BCI_CMD_LINE 0x5C000000 -#define BCI_CMD_LINE_LAST_PIXEL 0x58000000 -#define BCI_CMD_BYTE_TEXT 0x63000000 -#define BCI_CMD_NT_BYTE_TEXT 0x67000000 -#define BCI_CMD_BIT_TEXT 0x6C000000 -#define BCI_CMD_GET_ROP(cmd) (((cmd) >> 16) & 0xFF) -#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16)) -#define BCI_CMD_SEND_COLOR 0x00008000 - -#define BCI_CMD_CLIP_NONE 0x00000000 -#define BCI_CMD_CLIP_CURRENT 0x00002000 -#define BCI_CMD_CLIP_LR 0x00004000 -#define BCI_CMD_CLIP_NEW 0x00006000 - -#define BCI_CMD_DEST_GBD 0x00000000 -#define BCI_CMD_DEST_PBD 0x00000800 -#define BCI_CMD_DEST_PBD_NEW 0x00000C00 -#define BCI_CMD_DEST_SBD 0x00001000 -#define BCI_CMD_DEST_SBD_NEW 0x00001400 - -#define BCI_CMD_SRC_TRANSPARENT 0x00000200 -#define BCI_CMD_SRC_SOLID 0x00000000 -#define BCI_CMD_SRC_GBD 0x00000020 -#define BCI_CMD_SRC_COLOR 0x00000040 -#define BCI_CMD_SRC_MONO 0x00000060 -#define BCI_CMD_SRC_PBD_COLOR 0x00000080 -#define BCI_CMD_SRC_PBD_MONO 0x000000A0 -#define BCI_CMD_SRC_PBD_COLOR_NEW 0x000000C0 -#define BCI_CMD_SRC_PBD_MONO_NEW 0x000000E0 -#define BCI_CMD_SRC_SBD_COLOR 0x00000100 -#define BCI_CMD_SRC_SBD_MONO 0x00000120 -#define BCI_CMD_SRC_SBD_COLOR_NEW 0x00000140 -#define BCI_CMD_SRC_SBD_MONO_NEW 0x00000160 - -#define BCI_CMD_PAT_TRANSPARENT 0x00000010 -#define BCI_CMD_PAT_NONE 0x00000000 -#define BCI_CMD_PAT_COLOR 0x00000002 -#define BCI_CMD_PAT_MONO 0x00000003 -#define BCI_CMD_PAT_PBD_COLOR 0x00000004 -#define BCI_CMD_PAT_PBD_MONO 0x00000005 -#define BCI_CMD_PAT_PBD_COLOR_NEW 0x00000006 -#define BCI_CMD_PAT_PBD_MONO_NEW 0x00000007 -#define BCI_CMD_PAT_SBD_COLOR 0x00000008 -#define BCI_CMD_PAT_SBD_MONO 0x00000009 -#define BCI_CMD_PAT_SBD_COLOR_NEW 0x0000000A -#define BCI_CMD_PAT_SBD_MONO_NEW 0x0000000B - -#define BCI_BD_BW_DISABLE 0x10000000 -#define BCI_BD_TILE_MASK 0x03000000 -#define BCI_BD_TILE_NONE 0x00000000 -#define BCI_BD_TILE_16 0x02000000 -#define BCI_BD_TILE_32 0x03000000 -#define BCI_BD_GET_BPP(bd) (((bd) >> 16) & 0xFF) -#define BCI_BD_SET_BPP(bd, bpp) ((bd) |= (((bpp) & 0xFF) << 16)) -#define BCI_BD_GET_STRIDE(bd) ((bd) & 0xFFFF) -#define BCI_BD_SET_STRIDE(bd, st) ((bd) |= ((st) & 0xFFFF)) - -#define BCI_CMD_SET_REGISTER 0x96000000 - -#define BCI_CMD_WAIT 0xC0000000 -#define BCI_CMD_WAIT_3D 0x00010000 -#define BCI_CMD_WAIT_2D 0x00020000 - -#define BCI_CMD_UPDATE_EVENT_TAG 0x98000000 - -#define BCI_CMD_DRAW_PRIM 0x80000000 -#define BCI_CMD_DRAW_INDEXED_PRIM 0x88000000 -#define BCI_CMD_DRAW_CONT 0x01000000 -#define BCI_CMD_DRAW_TRILIST 0x00000000 -#define BCI_CMD_DRAW_TRISTRIP 0x02000000 -#define BCI_CMD_DRAW_TRIFAN 0x04000000 -#define BCI_CMD_DRAW_SKIPFLAGS 0x000000ff -#define BCI_CMD_DRAW_NO_Z 0x00000001 -#define BCI_CMD_DRAW_NO_W 0x00000002 -#define BCI_CMD_DRAW_NO_CD 0x00000004 -#define BCI_CMD_DRAW_NO_CS 0x00000008 -#define BCI_CMD_DRAW_NO_U0 0x00000010 -#define BCI_CMD_DRAW_NO_V0 0x00000020 -#define BCI_CMD_DRAW_NO_UV0 0x00000030 -#define BCI_CMD_DRAW_NO_U1 0x00000040 -#define BCI_CMD_DRAW_NO_V1 0x00000080 -#define BCI_CMD_DRAW_NO_UV1 0x000000c0 - -#define BCI_CMD_DMA 0xa8000000 - -#define BCI_W_H(w, h) ((((h) << 16) | (w)) & 0x0FFF0FFF) -#define BCI_X_Y(x, y) ((((y) << 16) | (x)) & 0x0FFF0FFF) -#define BCI_X_W(x, y) ((((w) << 16) | (x)) & 0x0FFF0FFF) -#define BCI_CLIP_LR(l, r) ((((r) << 16) | (l)) & 0x0FFF0FFF) -#define BCI_CLIP_TL(t, l) ((((t) << 16) | (l)) & 0x0FFF0FFF) -#define BCI_CLIP_BR(b, r) ((((b) << 16) | (r)) & 0x0FFF0FFF) - -#define BCI_LINE_X_Y(x, y) (((y) << 16) | ((x) & 0xFFFF)) -#define BCI_LINE_STEPS(diag, axi) (((axi) << 16) | ((diag) & 0xFFFF)) -#define BCI_LINE_MISC(maj, ym, xp, yp, err) \ - (((maj) & 0x1FFF) | \ - ((ym) ? 1<<13 : 0) | \ - ((xp) ? 1<<14 : 0) | \ - ((yp) ? 1<<15 : 0) | \ - ((err) << 16)) - -/* - * common commands - */ -#define BCI_SET_REGISTERS( first, n ) \ - BCI_WRITE(BCI_CMD_SET_REGISTER | \ - ((uint32_t)(n) & 0xff) << 16 | \ - ((uint32_t)(first) & 0xffff)) -#define DMA_SET_REGISTERS( first, n ) \ - DMA_WRITE(BCI_CMD_SET_REGISTER | \ - ((uint32_t)(n) & 0xff) << 16 | \ - ((uint32_t)(first) & 0xffff)) - -#define BCI_DRAW_PRIMITIVE(n, type, skip) \ - BCI_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \ - ((n) << 16)) -#define DMA_DRAW_PRIMITIVE(n, type, skip) \ - DMA_WRITE(BCI_CMD_DRAW_PRIM | (type) | (skip) | \ - ((n) << 16)) - -#define BCI_DRAW_INDICES_S3D(n, type, i0) \ - BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \ - ((n) << 16) | (i0)) - -#define BCI_DRAW_INDICES_S4(n, type, skip) \ - BCI_WRITE(BCI_CMD_DRAW_INDEXED_PRIM | (type) | \ - (skip) | ((n) << 16)) - -#define BCI_DMA(n) \ - BCI_WRITE(BCI_CMD_DMA | (((n) >> 1) - 1)) - -/* - * access to MMIO - */ -#define SAVAGE_READ(reg) \ - readl(((void __iomem *)dev_priv->mmio->handle) + (reg)) -#define SAVAGE_WRITE(reg) \ - writel(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) - -/* - * access to the burst command interface (BCI) - */ -#define SAVAGE_BCI_DEBUG 1 - -#define BCI_LOCALS volatile uint32_t *bci_ptr; - -#define BEGIN_BCI( n ) do { \ - dev_priv->wait_fifo(dev_priv, (n)); \ - bci_ptr = dev_priv->bci_ptr; \ -} while(0) - -#define BCI_WRITE( val ) *bci_ptr++ = (uint32_t)(val) - -/* - * command DMA support - */ -#define SAVAGE_DMA_DEBUG 1 - -#define DMA_LOCALS uint32_t *dma_ptr; - -#define BEGIN_DMA( n ) do { \ - unsigned int cur = dev_priv->current_dma_page; \ - unsigned int rest = SAVAGE_DMA_PAGE_SIZE - \ - dev_priv->dma_pages[cur].used; \ - if ((n) > rest) { \ - dma_ptr = savage_dma_alloc(dev_priv, (n)); \ - } else { /* fast path for small allocations */ \ - dma_ptr = (uint32_t *)dev_priv->cmd_dma->handle + \ - cur * SAVAGE_DMA_PAGE_SIZE + \ - dev_priv->dma_pages[cur].used; \ - if (dev_priv->dma_pages[cur].used == 0) \ - savage_dma_wait(dev_priv, cur); \ - dev_priv->dma_pages[cur].used += (n); \ - } \ -} while(0) - -#define DMA_WRITE( val ) *dma_ptr++ = (uint32_t)(val) - -#define DMA_COPY(src, n) do { \ - memcpy(dma_ptr, (src), (n)*4); \ - dma_ptr += n; \ -} while(0) - -#if SAVAGE_DMA_DEBUG -#define DMA_COMMIT() do { \ - unsigned int cur = dev_priv->current_dma_page; \ - uint32_t *expected = (uint32_t *)dev_priv->cmd_dma->handle + \ - cur * SAVAGE_DMA_PAGE_SIZE + \ - dev_priv->dma_pages[cur].used; \ - if (dma_ptr != expected) { \ - DRM_ERROR("DMA allocation and use don't match: " \ - "%p != %p\n", expected, dma_ptr); \ - savage_dma_reset(dev_priv); \ - } \ -} while(0) -#else -#define DMA_COMMIT() do {/* nothing */} while(0) -#endif - -#define DMA_FLUSH() dev_priv->dma_flush(dev_priv) - -/* Buffer aging via event tag - */ - -#define UPDATE_EVENT_COUNTER( ) do { \ - if (dev_priv->status_ptr) { \ - uint16_t count; \ - /* coordinate with Xserver */ \ - count = dev_priv->status_ptr[1023]; \ - if (count < dev_priv->event_counter) \ - dev_priv->event_wrap++; \ - dev_priv->event_counter = count; \ - } \ -} while(0) - -#define SET_AGE( age, e, w ) do { \ - (age)->event = e; \ - (age)->wrap = w; \ -} while(0) - -#define TEST_AGE( age, e, w ) \ - ( (age)->wrap < (w) || ( (age)->wrap == (w) && (age)->event <= (e) ) ) - -#endif /* __SAVAGE_DRV_H__ */ diff --git a/drivers/gpu/drm/savage/savage_state.c b/drivers/gpu/drm/savage/savage_state.c deleted file mode 100644 index e0d40ae67d54..000000000000 --- a/drivers/gpu/drm/savage/savage_state.c +++ /dev/null @@ -1,1169 +0,0 @@ -/* savage_state.c -- State and drawing support for Savage - * - * Copyright 2004 Felix Kuehling - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include - -#include -#include -#include -#include - -#include "savage_drv.h" - -void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, - const struct drm_clip_rect * pbox) -{ - uint32_t scstart = dev_priv->state.s3d.new_scstart; - uint32_t scend = dev_priv->state.s3d.new_scend; - scstart = (scstart & ~SAVAGE_SCISSOR_MASK_S3D) | - ((uint32_t) pbox->x1 & 0x000007ff) | - (((uint32_t) pbox->y1 << 16) & 0x07ff0000); - scend = (scend & ~SAVAGE_SCISSOR_MASK_S3D) | - (((uint32_t) pbox->x2 - 1) & 0x000007ff) | - ((((uint32_t) pbox->y2 - 1) << 16) & 0x07ff0000); - if (scstart != dev_priv->state.s3d.scstart || - scend != dev_priv->state.s3d.scend) { - DMA_LOCALS; - BEGIN_DMA(4); - DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D); - DMA_SET_REGISTERS(SAVAGE_SCSTART_S3D, 2); - DMA_WRITE(scstart); - DMA_WRITE(scend); - dev_priv->state.s3d.scstart = scstart; - dev_priv->state.s3d.scend = scend; - dev_priv->waiting = 1; - DMA_COMMIT(); - } -} - -void savage_emit_clip_rect_s4(drm_savage_private_t * dev_priv, - const struct drm_clip_rect * pbox) -{ - uint32_t drawctrl0 = dev_priv->state.s4.new_drawctrl0; - uint32_t drawctrl1 = dev_priv->state.s4.new_drawctrl1; - drawctrl0 = (drawctrl0 & ~SAVAGE_SCISSOR_MASK_S4) | - ((uint32_t) pbox->x1 & 0x000007ff) | - (((uint32_t) pbox->y1 << 12) & 0x00fff000); - drawctrl1 = (drawctrl1 & ~SAVAGE_SCISSOR_MASK_S4) | - (((uint32_t) pbox->x2 - 1) & 0x000007ff) | - ((((uint32_t) pbox->y2 - 1) << 12) & 0x00fff000); - if (drawctrl0 != dev_priv->state.s4.drawctrl0 || - drawctrl1 != dev_priv->state.s4.drawctrl1) { - DMA_LOCALS; - BEGIN_DMA(4); - DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D); - DMA_SET_REGISTERS(SAVAGE_DRAWCTRL0_S4, 2); - DMA_WRITE(drawctrl0); - DMA_WRITE(drawctrl1); - dev_priv->state.s4.drawctrl0 = drawctrl0; - dev_priv->state.s4.drawctrl1 = drawctrl1; - dev_priv->waiting = 1; - DMA_COMMIT(); - } -} - -static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit, - uint32_t addr) -{ - if ((addr & 6) != 2) { /* reserved bits */ - DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr); - return -EINVAL; - } - if (!(addr & 1)) { /* local */ - addr &= ~7; - if (addr < dev_priv->texture_offset || - addr >= dev_priv->texture_offset + dev_priv->texture_size) { - DRM_ERROR - ("bad texAddr%d %08x (local addr out of range)\n", - unit, addr); - return -EINVAL; - } - } else { /* AGP */ - if (!dev_priv->agp_textures) { - DRM_ERROR("bad texAddr%d %08x (AGP not available)\n", - unit, addr); - return -EINVAL; - } - addr &= ~7; - if (addr < dev_priv->agp_textures->offset || - addr >= (dev_priv->agp_textures->offset + - dev_priv->agp_textures->size)) { - DRM_ERROR - ("bad texAddr%d %08x (AGP addr out of range)\n", - unit, addr); - return -EINVAL; - } - } - return 0; -} - -#define SAVE_STATE(reg,where) \ - if(start <= reg && start+count > reg) \ - dev_priv->state.where = regs[reg - start] -#define SAVE_STATE_MASK(reg,where,mask) do { \ - if(start <= reg && start+count > reg) { \ - uint32_t tmp; \ - tmp = regs[reg - start]; \ - dev_priv->state.where = (tmp & (mask)) | \ - (dev_priv->state.where & ~(mask)); \ - } \ -} while (0) - -static int savage_verify_state_s3d(drm_savage_private_t * dev_priv, - unsigned int start, unsigned int count, - const uint32_t *regs) -{ - if (start < SAVAGE_TEXPALADDR_S3D || - start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) { - DRM_ERROR("invalid register range (0x%04x-0x%04x)\n", - start, start + count - 1); - return -EINVAL; - } - - SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart, - ~SAVAGE_SCISSOR_MASK_S3D); - SAVE_STATE_MASK(SAVAGE_SCEND_S3D, s3d.new_scend, - ~SAVAGE_SCISSOR_MASK_S3D); - - /* if any texture regs were changed ... */ - if (start <= SAVAGE_TEXCTRL_S3D && - start + count > SAVAGE_TEXPALADDR_S3D) { - /* ... check texture state */ - SAVE_STATE(SAVAGE_TEXCTRL_S3D, s3d.texctrl); - SAVE_STATE(SAVAGE_TEXADDR_S3D, s3d.texaddr); - if (dev_priv->state.s3d.texctrl & SAVAGE_TEXCTRL_TEXEN_MASK) - return savage_verify_texaddr(dev_priv, 0, - dev_priv->state.s3d.texaddr); - } - - return 0; -} - -static int savage_verify_state_s4(drm_savage_private_t * dev_priv, - unsigned int start, unsigned int count, - const uint32_t *regs) -{ - int ret = 0; - - if (start < SAVAGE_DRAWLOCALCTRL_S4 || - start + count - 1 > SAVAGE_TEXBLENDCOLOR_S4) { - DRM_ERROR("invalid register range (0x%04x-0x%04x)\n", - start, start + count - 1); - return -EINVAL; - } - - SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0, - ~SAVAGE_SCISSOR_MASK_S4); - SAVE_STATE_MASK(SAVAGE_DRAWCTRL1_S4, s4.new_drawctrl1, - ~SAVAGE_SCISSOR_MASK_S4); - - /* if any texture regs were changed ... */ - if (start <= SAVAGE_TEXDESCR_S4 && - start + count > SAVAGE_TEXPALADDR_S4) { - /* ... check texture state */ - SAVE_STATE(SAVAGE_TEXDESCR_S4, s4.texdescr); - SAVE_STATE(SAVAGE_TEXADDR0_S4, s4.texaddr0); - SAVE_STATE(SAVAGE_TEXADDR1_S4, s4.texaddr1); - if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX0EN_MASK) - ret |= savage_verify_texaddr(dev_priv, 0, - dev_priv->state.s4.texaddr0); - if (dev_priv->state.s4.texdescr & SAVAGE_TEXDESCR_TEX1EN_MASK) - ret |= savage_verify_texaddr(dev_priv, 1, - dev_priv->state.s4.texaddr1); - } - - return ret; -} - -#undef SAVE_STATE -#undef SAVE_STATE_MASK - -static int savage_dispatch_state(drm_savage_private_t * dev_priv, - const drm_savage_cmd_header_t * cmd_header, - const uint32_t *regs) -{ - unsigned int count = cmd_header->state.count; - unsigned int start = cmd_header->state.start; - unsigned int count2 = 0; - unsigned int bci_size; - int ret; - DMA_LOCALS; - - if (!count) - return 0; - - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - ret = savage_verify_state_s3d(dev_priv, start, count, regs); - if (ret != 0) - return ret; - /* scissor regs are emitted in savage_dispatch_draw */ - if (start < SAVAGE_SCSTART_S3D) { - if (start + count > SAVAGE_SCEND_S3D + 1) - count2 = count - (SAVAGE_SCEND_S3D + 1 - start); - if (start + count > SAVAGE_SCSTART_S3D) - count = SAVAGE_SCSTART_S3D - start; - } else if (start <= SAVAGE_SCEND_S3D) { - if (start + count > SAVAGE_SCEND_S3D + 1) { - count -= SAVAGE_SCEND_S3D + 1 - start; - start = SAVAGE_SCEND_S3D + 1; - } else - return 0; - } - } else { - ret = savage_verify_state_s4(dev_priv, start, count, regs); - if (ret != 0) - return ret; - /* scissor regs are emitted in savage_dispatch_draw */ - if (start < SAVAGE_DRAWCTRL0_S4) { - if (start + count > SAVAGE_DRAWCTRL1_S4 + 1) - count2 = count - - (SAVAGE_DRAWCTRL1_S4 + 1 - start); - if (start + count > SAVAGE_DRAWCTRL0_S4) - count = SAVAGE_DRAWCTRL0_S4 - start; - } else if (start <= SAVAGE_DRAWCTRL1_S4) { - if (start + count > SAVAGE_DRAWCTRL1_S4 + 1) { - count -= SAVAGE_DRAWCTRL1_S4 + 1 - start; - start = SAVAGE_DRAWCTRL1_S4 + 1; - } else - return 0; - } - } - - bci_size = count + (count + 254) / 255 + count2 + (count2 + 254) / 255; - - if (cmd_header->state.global) { - BEGIN_DMA(bci_size + 1); - DMA_WRITE(BCI_CMD_WAIT | BCI_CMD_WAIT_3D); - dev_priv->waiting = 1; - } else { - BEGIN_DMA(bci_size); - } - - do { - while (count > 0) { - unsigned int n = count < 255 ? count : 255; - DMA_SET_REGISTERS(start, n); - DMA_COPY(regs, n); - count -= n; - start += n; - regs += n; - } - start += 2; - regs += 2; - count = count2; - count2 = 0; - } while (count); - - DMA_COMMIT(); - - return 0; -} - -static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv, - const drm_savage_cmd_header_t * cmd_header, - const struct drm_buf * dmabuf) -{ - unsigned char reorder = 0; - unsigned int prim = cmd_header->prim.prim; - unsigned int skip = cmd_header->prim.skip; - unsigned int n = cmd_header->prim.count; - unsigned int start = cmd_header->prim.start; - unsigned int i; - BCI_LOCALS; - - if (!dmabuf) { - DRM_ERROR("called without dma buffers!\n"); - return -EINVAL; - } - - if (!n) - return 0; - - switch (prim) { - case SAVAGE_PRIM_TRILIST_201: - reorder = 1; - prim = SAVAGE_PRIM_TRILIST; - fallthrough; - case SAVAGE_PRIM_TRILIST: - if (n % 3 != 0) { - DRM_ERROR("wrong number of vertices %u in TRILIST\n", - n); - return -EINVAL; - } - break; - case SAVAGE_PRIM_TRISTRIP: - case SAVAGE_PRIM_TRIFAN: - if (n < 3) { - DRM_ERROR - ("wrong number of vertices %u in TRIFAN/STRIP\n", - n); - return -EINVAL; - } - break; - default: - DRM_ERROR("invalid primitive type %u\n", prim); - return -EINVAL; - } - - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - if (skip != 0) { - DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return -EINVAL; - } - } else { - unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) - - (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) - - (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1); - if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) { - DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return -EINVAL; - } - if (reorder) { - DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); - return -EINVAL; - } - } - - if (start + n > dmabuf->total / 32) { - DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n", - start, start + n - 1, dmabuf->total / 32); - return -EINVAL; - } - - /* Vertex DMA doesn't work with command DMA at the same time, - * so we use BCI_... to submit commands here. Flush buffered - * faked DMA first. */ - DMA_FLUSH(); - - if (dmabuf->bus_address != dev_priv->state.common.vbaddr) { - BEGIN_BCI(2); - BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1); - BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type); - dev_priv->state.common.vbaddr = dmabuf->bus_address; - } - if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) { - /* Workaround for what looks like a hardware bug. If a - * WAIT_3D_IDLE was emitted some time before the - * indexed drawing command then the engine will lock - * up. There are two known workarounds: - * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */ - BEGIN_BCI(63); - for (i = 0; i < 63; ++i) - BCI_WRITE(BCI_CMD_WAIT); - dev_priv->waiting = 0; - } - - prim <<= 25; - while (n != 0) { - /* Can emit up to 255 indices (85 triangles) at once. */ - unsigned int count = n > 255 ? 255 : n; - if (reorder) { - /* Need to reorder indices for correct flat - * shading while preserving the clock sense - * for correct culling. Only on Savage3D. */ - int reorder[3] = { -1, -1, -1 }; - reorder[start % 3] = 2; - - BEGIN_BCI((count + 1 + 1) / 2); - BCI_DRAW_INDICES_S3D(count, prim, start + 2); - - for (i = start + 1; i + 1 < start + count; i += 2) - BCI_WRITE((i + reorder[i % 3]) | - ((i + 1 + - reorder[(i + 1) % 3]) << 16)); - if (i < start + count) - BCI_WRITE(i + reorder[i % 3]); - } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - BEGIN_BCI((count + 1 + 1) / 2); - BCI_DRAW_INDICES_S3D(count, prim, start); - - for (i = start + 1; i + 1 < start + count; i += 2) - BCI_WRITE(i | ((i + 1) << 16)); - if (i < start + count) - BCI_WRITE(i); - } else { - BEGIN_BCI((count + 2 + 1) / 2); - BCI_DRAW_INDICES_S4(count, prim, skip); - - for (i = start; i + 1 < start + count; i += 2) - BCI_WRITE(i | ((i + 1) << 16)); - if (i < start + count) - BCI_WRITE(i); - } - - start += count; - n -= count; - - prim |= BCI_CMD_DRAW_CONT; - } - - return 0; -} - -static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, - const drm_savage_cmd_header_t * cmd_header, - const uint32_t *vtxbuf, unsigned int vb_size, - unsigned int vb_stride) -{ - unsigned char reorder = 0; - unsigned int prim = cmd_header->prim.prim; - unsigned int skip = cmd_header->prim.skip; - unsigned int n = cmd_header->prim.count; - unsigned int start = cmd_header->prim.start; - unsigned int vtx_size; - unsigned int i; - DMA_LOCALS; - - if (!n) - return 0; - - switch (prim) { - case SAVAGE_PRIM_TRILIST_201: - reorder = 1; - prim = SAVAGE_PRIM_TRILIST; - fallthrough; - case SAVAGE_PRIM_TRILIST: - if (n % 3 != 0) { - DRM_ERROR("wrong number of vertices %u in TRILIST\n", - n); - return -EINVAL; - } - break; - case SAVAGE_PRIM_TRISTRIP: - case SAVAGE_PRIM_TRIFAN: - if (n < 3) { - DRM_ERROR - ("wrong number of vertices %u in TRIFAN/STRIP\n", - n); - return -EINVAL; - } - break; - default: - DRM_ERROR("invalid primitive type %u\n", prim); - return -EINVAL; - } - - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - if (skip > SAVAGE_SKIP_ALL_S3D) { - DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return -EINVAL; - } - vtx_size = 8; /* full vertex */ - } else { - if (skip > SAVAGE_SKIP_ALL_S4) { - DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return -EINVAL; - } - vtx_size = 10; /* full vertex */ - } - - vtx_size -= (skip & 1) + (skip >> 1 & 1) + - (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) + - (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1); - - if (vtx_size > vb_stride) { - DRM_ERROR("vertex size greater than vb stride (%u > %u)\n", - vtx_size, vb_stride); - return -EINVAL; - } - - if (start + n > vb_size / (vb_stride * 4)) { - DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n", - start, start + n - 1, vb_size / (vb_stride * 4)); - return -EINVAL; - } - - prim <<= 25; - while (n != 0) { - /* Can emit up to 255 vertices (85 triangles) at once. */ - unsigned int count = n > 255 ? 255 : n; - if (reorder) { - /* Need to reorder vertices for correct flat - * shading while preserving the clock sense - * for correct culling. Only on Savage3D. */ - int reorder[3] = { -1, -1, -1 }; - reorder[start % 3] = 2; - - BEGIN_DMA(count * vtx_size + 1); - DMA_DRAW_PRIMITIVE(count, prim, skip); - - for (i = start; i < start + count; ++i) { - unsigned int j = i + reorder[i % 3]; - DMA_COPY(&vtxbuf[vb_stride * j], vtx_size); - } - - DMA_COMMIT(); - } else { - BEGIN_DMA(count * vtx_size + 1); - DMA_DRAW_PRIMITIVE(count, prim, skip); - - if (vb_stride == vtx_size) { - DMA_COPY(&vtxbuf[vb_stride * start], - vtx_size * count); - } else { - for (i = start; i < start + count; ++i) { - DMA_COPY(&vtxbuf [vb_stride * i], - vtx_size); - } - } - - DMA_COMMIT(); - } - - start += count; - n -= count; - - prim |= BCI_CMD_DRAW_CONT; - } - - return 0; -} - -static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, - const drm_savage_cmd_header_t * cmd_header, - const uint16_t *idx, - const struct drm_buf * dmabuf) -{ - unsigned char reorder = 0; - unsigned int prim = cmd_header->idx.prim; - unsigned int skip = cmd_header->idx.skip; - unsigned int n = cmd_header->idx.count; - unsigned int i; - BCI_LOCALS; - - if (!dmabuf) { - DRM_ERROR("called without dma buffers!\n"); - return -EINVAL; - } - - if (!n) - return 0; - - switch (prim) { - case SAVAGE_PRIM_TRILIST_201: - reorder = 1; - prim = SAVAGE_PRIM_TRILIST; - fallthrough; - case SAVAGE_PRIM_TRILIST: - if (n % 3 != 0) { - DRM_ERROR("wrong number of indices %u in TRILIST\n", n); - return -EINVAL; - } - break; - case SAVAGE_PRIM_TRISTRIP: - case SAVAGE_PRIM_TRIFAN: - if (n < 3) { - DRM_ERROR - ("wrong number of indices %u in TRIFAN/STRIP\n", n); - return -EINVAL; - } - break; - default: - DRM_ERROR("invalid primitive type %u\n", prim); - return -EINVAL; - } - - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - if (skip != 0) { - DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return -EINVAL; - } - } else { - unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) - - (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) - - (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1); - if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) { - DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return -EINVAL; - } - if (reorder) { - DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); - return -EINVAL; - } - } - - /* Vertex DMA doesn't work with command DMA at the same time, - * so we use BCI_... to submit commands here. Flush buffered - * faked DMA first. */ - DMA_FLUSH(); - - if (dmabuf->bus_address != dev_priv->state.common.vbaddr) { - BEGIN_BCI(2); - BCI_SET_REGISTERS(SAVAGE_VERTBUFADDR, 1); - BCI_WRITE(dmabuf->bus_address | dev_priv->dma_type); - dev_priv->state.common.vbaddr = dmabuf->bus_address; - } - if (S3_SAVAGE3D_SERIES(dev_priv->chipset) && dev_priv->waiting) { - /* Workaround for what looks like a hardware bug. If a - * WAIT_3D_IDLE was emitted some time before the - * indexed drawing command then the engine will lock - * up. There are two known workarounds: - * WAIT_IDLE_EMPTY or emit at least 63 NOPs. */ - BEGIN_BCI(63); - for (i = 0; i < 63; ++i) - BCI_WRITE(BCI_CMD_WAIT); - dev_priv->waiting = 0; - } - - prim <<= 25; - while (n != 0) { - /* Can emit up to 255 indices (85 triangles) at once. */ - unsigned int count = n > 255 ? 255 : n; - - /* check indices */ - for (i = 0; i < count; ++i) { - if (idx[i] > dmabuf->total / 32) { - DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", - i, idx[i], dmabuf->total / 32); - return -EINVAL; - } - } - - if (reorder) { - /* Need to reorder indices for correct flat - * shading while preserving the clock sense - * for correct culling. Only on Savage3D. */ - int reorder[3] = { 2, -1, -1 }; - - BEGIN_BCI((count + 1 + 1) / 2); - BCI_DRAW_INDICES_S3D(count, prim, idx[2]); - - for (i = 1; i + 1 < count; i += 2) - BCI_WRITE(idx[i + reorder[i % 3]] | - (idx[i + 1 + - reorder[(i + 1) % 3]] << 16)); - if (i < count) - BCI_WRITE(idx[i + reorder[i % 3]]); - } else if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - BEGIN_BCI((count + 1 + 1) / 2); - BCI_DRAW_INDICES_S3D(count, prim, idx[0]); - - for (i = 1; i + 1 < count; i += 2) - BCI_WRITE(idx[i] | (idx[i + 1] << 16)); - if (i < count) - BCI_WRITE(idx[i]); - } else { - BEGIN_BCI((count + 2 + 1) / 2); - BCI_DRAW_INDICES_S4(count, prim, skip); - - for (i = 0; i + 1 < count; i += 2) - BCI_WRITE(idx[i] | (idx[i + 1] << 16)); - if (i < count) - BCI_WRITE(idx[i]); - } - - idx += count; - n -= count; - - prim |= BCI_CMD_DRAW_CONT; - } - - return 0; -} - -static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, - const drm_savage_cmd_header_t * cmd_header, - const uint16_t *idx, - const uint32_t *vtxbuf, - unsigned int vb_size, unsigned int vb_stride) -{ - unsigned char reorder = 0; - unsigned int prim = cmd_header->idx.prim; - unsigned int skip = cmd_header->idx.skip; - unsigned int n = cmd_header->idx.count; - unsigned int vtx_size; - unsigned int i; - DMA_LOCALS; - - if (!n) - return 0; - - switch (prim) { - case SAVAGE_PRIM_TRILIST_201: - reorder = 1; - prim = SAVAGE_PRIM_TRILIST; - fallthrough; - case SAVAGE_PRIM_TRILIST: - if (n % 3 != 0) { - DRM_ERROR("wrong number of indices %u in TRILIST\n", n); - return -EINVAL; - } - break; - case SAVAGE_PRIM_TRISTRIP: - case SAVAGE_PRIM_TRIFAN: - if (n < 3) { - DRM_ERROR - ("wrong number of indices %u in TRIFAN/STRIP\n", n); - return -EINVAL; - } - break; - default: - DRM_ERROR("invalid primitive type %u\n", prim); - return -EINVAL; - } - - if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { - if (skip > SAVAGE_SKIP_ALL_S3D) { - DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return -EINVAL; - } - vtx_size = 8; /* full vertex */ - } else { - if (skip > SAVAGE_SKIP_ALL_S4) { - DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return -EINVAL; - } - vtx_size = 10; /* full vertex */ - } - - vtx_size -= (skip & 1) + (skip >> 1 & 1) + - (skip >> 2 & 1) + (skip >> 3 & 1) + (skip >> 4 & 1) + - (skip >> 5 & 1) + (skip >> 6 & 1) + (skip >> 7 & 1); - - if (vtx_size > vb_stride) { - DRM_ERROR("vertex size greater than vb stride (%u > %u)\n", - vtx_size, vb_stride); - return -EINVAL; - } - - prim <<= 25; - while (n != 0) { - /* Can emit up to 255 vertices (85 triangles) at once. */ - unsigned int count = n > 255 ? 255 : n; - - /* Check indices */ - for (i = 0; i < count; ++i) { - if (idx[i] > vb_size / (vb_stride * 4)) { - DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", - i, idx[i], vb_size / (vb_stride * 4)); - return -EINVAL; - } - } - - if (reorder) { - /* Need to reorder vertices for correct flat - * shading while preserving the clock sense - * for correct culling. Only on Savage3D. */ - int reorder[3] = { 2, -1, -1 }; - - BEGIN_DMA(count * vtx_size + 1); - DMA_DRAW_PRIMITIVE(count, prim, skip); - - for (i = 0; i < count; ++i) { - unsigned int j = idx[i + reorder[i % 3]]; - DMA_COPY(&vtxbuf[vb_stride * j], vtx_size); - } - - DMA_COMMIT(); - } else { - BEGIN_DMA(count * vtx_size + 1); - DMA_DRAW_PRIMITIVE(count, prim, skip); - - for (i = 0; i < count; ++i) { - unsigned int j = idx[i]; - DMA_COPY(&vtxbuf[vb_stride * j], vtx_size); - } - - DMA_COMMIT(); - } - - idx += count; - n -= count; - - prim |= BCI_CMD_DRAW_CONT; - } - - return 0; -} - -static int savage_dispatch_clear(drm_savage_private_t * dev_priv, - const drm_savage_cmd_header_t * cmd_header, - const drm_savage_cmd_header_t *data, - unsigned int nbox, - const struct drm_clip_rect *boxes) -{ - unsigned int flags = cmd_header->clear0.flags; - unsigned int clear_cmd; - unsigned int i, nbufs; - DMA_LOCALS; - - if (nbox == 0) - return 0; - - clear_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP | - BCI_CMD_SEND_COLOR | BCI_CMD_DEST_PBD_NEW; - BCI_CMD_SET_ROP(clear_cmd, 0xCC); - - nbufs = ((flags & SAVAGE_FRONT) ? 1 : 0) + - ((flags & SAVAGE_BACK) ? 1 : 0) + ((flags & SAVAGE_DEPTH) ? 1 : 0); - if (nbufs == 0) - return 0; - - if (data->clear1.mask != 0xffffffff) { - /* set mask */ - BEGIN_DMA(2); - DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1); - DMA_WRITE(data->clear1.mask); - DMA_COMMIT(); - } - for (i = 0; i < nbox; ++i) { - unsigned int x, y, w, h; - unsigned int buf; - x = boxes[i].x1, y = boxes[i].y1; - w = boxes[i].x2 - boxes[i].x1; - h = boxes[i].y2 - boxes[i].y1; - BEGIN_DMA(nbufs * 6); - for (buf = SAVAGE_FRONT; buf <= SAVAGE_DEPTH; buf <<= 1) { - if (!(flags & buf)) - continue; - DMA_WRITE(clear_cmd); - switch (buf) { - case SAVAGE_FRONT: - DMA_WRITE(dev_priv->front_offset); - DMA_WRITE(dev_priv->front_bd); - break; - case SAVAGE_BACK: - DMA_WRITE(dev_priv->back_offset); - DMA_WRITE(dev_priv->back_bd); - break; - case SAVAGE_DEPTH: - DMA_WRITE(dev_priv->depth_offset); - DMA_WRITE(dev_priv->depth_bd); - break; - } - DMA_WRITE(data->clear1.value); - DMA_WRITE(BCI_X_Y(x, y)); - DMA_WRITE(BCI_W_H(w, h)); - } - DMA_COMMIT(); - } - if (data->clear1.mask != 0xffffffff) { - /* reset mask */ - BEGIN_DMA(2); - DMA_SET_REGISTERS(SAVAGE_BITPLANEWTMASK, 1); - DMA_WRITE(0xffffffff); - DMA_COMMIT(); - } - - return 0; -} - -static int savage_dispatch_swap(drm_savage_private_t * dev_priv, - unsigned int nbox, const struct drm_clip_rect *boxes) -{ - unsigned int swap_cmd; - unsigned int i; - DMA_LOCALS; - - if (nbox == 0) - return 0; - - swap_cmd = BCI_CMD_RECT | BCI_CMD_RECT_XP | BCI_CMD_RECT_YP | - BCI_CMD_SRC_PBD_COLOR_NEW | BCI_CMD_DEST_GBD; - BCI_CMD_SET_ROP(swap_cmd, 0xCC); - - for (i = 0; i < nbox; ++i) { - BEGIN_DMA(6); - DMA_WRITE(swap_cmd); - DMA_WRITE(dev_priv->back_offset); - DMA_WRITE(dev_priv->back_bd); - DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1)); - DMA_WRITE(BCI_X_Y(boxes[i].x1, boxes[i].y1)); - DMA_WRITE(BCI_W_H(boxes[i].x2 - boxes[i].x1, - boxes[i].y2 - boxes[i].y1)); - DMA_COMMIT(); - } - - return 0; -} - -static int savage_dispatch_draw(drm_savage_private_t * dev_priv, - const drm_savage_cmd_header_t *start, - const drm_savage_cmd_header_t *end, - const struct drm_buf * dmabuf, - const unsigned int *vtxbuf, - unsigned int vb_size, unsigned int vb_stride, - unsigned int nbox, - const struct drm_clip_rect *boxes) -{ - unsigned int i, j; - int ret; - - for (i = 0; i < nbox; ++i) { - const drm_savage_cmd_header_t *cmdbuf; - dev_priv->emit_clip_rect(dev_priv, &boxes[i]); - - cmdbuf = start; - while (cmdbuf < end) { - drm_savage_cmd_header_t cmd_header; - cmd_header = *cmdbuf; - cmdbuf++; - switch (cmd_header.cmd.cmd) { - case SAVAGE_CMD_DMA_PRIM: - ret = savage_dispatch_dma_prim( - dev_priv, &cmd_header, dmabuf); - break; - case SAVAGE_CMD_VB_PRIM: - ret = savage_dispatch_vb_prim( - dev_priv, &cmd_header, - vtxbuf, vb_size, vb_stride); - break; - case SAVAGE_CMD_DMA_IDX: - j = (cmd_header.idx.count + 3) / 4; - /* j was check in savage_bci_cmdbuf */ - ret = savage_dispatch_dma_idx(dev_priv, - &cmd_header, (const uint16_t *)cmdbuf, - dmabuf); - cmdbuf += j; - break; - case SAVAGE_CMD_VB_IDX: - j = (cmd_header.idx.count + 3) / 4; - /* j was check in savage_bci_cmdbuf */ - ret = savage_dispatch_vb_idx(dev_priv, - &cmd_header, (const uint16_t *)cmdbuf, - (const uint32_t *)vtxbuf, vb_size, - vb_stride); - cmdbuf += j; - break; - default: - /* What's the best return code? EFAULT? */ - DRM_ERROR("IMPLEMENTATION ERROR: " - "non-drawing-command %d\n", - cmd_header.cmd.cmd); - return -EINVAL; - } - - if (ret != 0) - return ret; - } - } - - return 0; -} - -int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_savage_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *dmabuf; - drm_savage_cmdbuf_t *cmdbuf = data; - drm_savage_cmd_header_t *kcmd_addr = NULL; - drm_savage_cmd_header_t *first_draw_cmd; - unsigned int *kvb_addr = NULL; - struct drm_clip_rect *kbox_addr = NULL; - unsigned int i, j; - int ret = 0; - - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (dma && dma->buflist) { - if (cmdbuf->dma_idx >= dma->buf_count) { - DRM_ERROR - ("vertex buffer index %u out of range (0-%u)\n", - cmdbuf->dma_idx, dma->buf_count - 1); - return -EINVAL; - } - dmabuf = dma->buflist[cmdbuf->dma_idx]; - } else { - dmabuf = NULL; - } - - /* Copy the user buffers into kernel temporary areas. This hasn't been - * a performance loss compared to VERIFYAREA_READ/ - * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct - * for locking on FreeBSD. - */ - if (cmdbuf->size) { - kcmd_addr = kmalloc_array(cmdbuf->size, 8, GFP_KERNEL); - if (kcmd_addr == NULL) - return -ENOMEM; - - if (copy_from_user(kcmd_addr, cmdbuf->cmd_addr, - cmdbuf->size * 8)) - { - kfree(kcmd_addr); - return -EFAULT; - } - cmdbuf->cmd_addr = kcmd_addr; - } - if (cmdbuf->vb_size) { - kvb_addr = memdup_user(cmdbuf->vb_addr, cmdbuf->vb_size); - if (IS_ERR(kvb_addr)) { - ret = PTR_ERR(kvb_addr); - kvb_addr = NULL; - goto done; - } - cmdbuf->vb_addr = kvb_addr; - } - if (cmdbuf->nbox) { - kbox_addr = kmalloc_array(cmdbuf->nbox, sizeof(struct drm_clip_rect), - GFP_KERNEL); - if (kbox_addr == NULL) { - ret = -ENOMEM; - goto done; - } - - if (copy_from_user(kbox_addr, cmdbuf->box_addr, - cmdbuf->nbox * sizeof(struct drm_clip_rect))) { - ret = -EFAULT; - goto done; - } - cmdbuf->box_addr = kbox_addr; - } - - /* Make sure writes to DMA buffers are finished before sending - * DMA commands to the graphics hardware. */ - mb(); - - /* Coming from user space. Don't know if the Xserver has - * emitted wait commands. Assuming the worst. */ - dev_priv->waiting = 1; - - i = 0; - first_draw_cmd = NULL; - while (i < cmdbuf->size) { - drm_savage_cmd_header_t cmd_header; - cmd_header = *(drm_savage_cmd_header_t *)cmdbuf->cmd_addr; - cmdbuf->cmd_addr++; - i++; - - /* Group drawing commands with same state to minimize - * iterations over clip rects. */ - j = 0; - switch (cmd_header.cmd.cmd) { - case SAVAGE_CMD_DMA_IDX: - case SAVAGE_CMD_VB_IDX: - j = (cmd_header.idx.count + 3) / 4; - if (i + j > cmdbuf->size) { - DRM_ERROR("indexed drawing command extends " - "beyond end of command buffer\n"); - DMA_FLUSH(); - ret = -EINVAL; - goto done; - } - fallthrough; - case SAVAGE_CMD_DMA_PRIM: - case SAVAGE_CMD_VB_PRIM: - if (!first_draw_cmd) - first_draw_cmd = cmdbuf->cmd_addr - 1; - cmdbuf->cmd_addr += j; - i += j; - break; - default: - if (first_draw_cmd) { - ret = savage_dispatch_draw( - dev_priv, first_draw_cmd, - cmdbuf->cmd_addr - 1, - dmabuf, cmdbuf->vb_addr, cmdbuf->vb_size, - cmdbuf->vb_stride, - cmdbuf->nbox, cmdbuf->box_addr); - if (ret != 0) - goto done; - first_draw_cmd = NULL; - } - } - if (first_draw_cmd) - continue; - - switch (cmd_header.cmd.cmd) { - case SAVAGE_CMD_STATE: - j = (cmd_header.state.count + 1) / 2; - if (i + j > cmdbuf->size) { - DRM_ERROR("command SAVAGE_CMD_STATE extends " - "beyond end of command buffer\n"); - DMA_FLUSH(); - ret = -EINVAL; - goto done; - } - ret = savage_dispatch_state(dev_priv, &cmd_header, - (const uint32_t *)cmdbuf->cmd_addr); - cmdbuf->cmd_addr += j; - i += j; - break; - case SAVAGE_CMD_CLEAR: - if (i + 1 > cmdbuf->size) { - DRM_ERROR("command SAVAGE_CMD_CLEAR extends " - "beyond end of command buffer\n"); - DMA_FLUSH(); - ret = -EINVAL; - goto done; - } - ret = savage_dispatch_clear(dev_priv, &cmd_header, - cmdbuf->cmd_addr, - cmdbuf->nbox, - cmdbuf->box_addr); - cmdbuf->cmd_addr++; - i++; - break; - case SAVAGE_CMD_SWAP: - ret = savage_dispatch_swap(dev_priv, cmdbuf->nbox, - cmdbuf->box_addr); - break; - default: - DRM_ERROR("invalid command 0x%x\n", - cmd_header.cmd.cmd); - DMA_FLUSH(); - ret = -EINVAL; - goto done; - } - - if (ret != 0) { - DMA_FLUSH(); - goto done; - } - } - - if (first_draw_cmd) { - ret = savage_dispatch_draw ( - dev_priv, first_draw_cmd, cmdbuf->cmd_addr, dmabuf, - cmdbuf->vb_addr, cmdbuf->vb_size, cmdbuf->vb_stride, - cmdbuf->nbox, cmdbuf->box_addr); - if (ret != 0) { - DMA_FLUSH(); - goto done; - } - } - - DMA_FLUSH(); - - if (dmabuf && cmdbuf->discard) { - drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private; - uint16_t event; - event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D); - SET_AGE(&buf_priv->age, event, dev_priv->event_wrap); - savage_freelist_put(dev, dmabuf); - } - -done: - /* If we didn't need to allocate them, these'll be NULL */ - kfree(kcmd_addr); - kfree(kvb_addr); - kfree(kbox_addr); - - return ret; -} diff --git a/include/uapi/drm/savage_drm.h b/include/uapi/drm/savage_drm.h deleted file mode 100644 index 0f6eddef74aa..000000000000 --- a/include/uapi/drm/savage_drm.h +++ /dev/null @@ -1,220 +0,0 @@ -/* savage_drm.h -- Public header for the savage driver - * - * Copyright 2004 Felix Kuehling - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sub license, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL FELIX KUEHLING BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF - * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __SAVAGE_DRM_H__ -#define __SAVAGE_DRM_H__ - -#include "drm.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -#ifndef __SAVAGE_SAREA_DEFINES__ -#define __SAVAGE_SAREA_DEFINES__ - -/* 2 heaps (1 for card, 1 for agp), each divided into up to 128 - * regions, subject to a minimum region size of (1<<16) == 64k. - * - * Clients may subdivide regions internally, but when sharing between - * clients, the region size is the minimum granularity. - */ - -#define SAVAGE_CARD_HEAP 0 -#define SAVAGE_AGP_HEAP 1 -#define SAVAGE_NR_TEX_HEAPS 2 -#define SAVAGE_NR_TEX_REGIONS 16 -#define SAVAGE_LOG_MIN_TEX_REGION_SIZE 16 - -#endif /* __SAVAGE_SAREA_DEFINES__ */ - -typedef struct _drm_savage_sarea { - /* LRU lists for texture memory in agp space and on the card. - */ - struct drm_tex_region texList[SAVAGE_NR_TEX_HEAPS][SAVAGE_NR_TEX_REGIONS + - 1]; - unsigned int texAge[SAVAGE_NR_TEX_HEAPS]; - - /* Mechanism to validate card state. - */ - int ctxOwner; -} drm_savage_sarea_t, *drm_savage_sarea_ptr; - -/* Savage-specific ioctls - */ -#define DRM_SAVAGE_BCI_INIT 0x00 -#define DRM_SAVAGE_BCI_CMDBUF 0x01 -#define DRM_SAVAGE_BCI_EVENT_EMIT 0x02 -#define DRM_SAVAGE_BCI_EVENT_WAIT 0x03 - -#define DRM_IOCTL_SAVAGE_BCI_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_INIT, drm_savage_init_t) -#define DRM_IOCTL_SAVAGE_BCI_CMDBUF DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_CMDBUF, drm_savage_cmdbuf_t) -#define DRM_IOCTL_SAVAGE_BCI_EVENT_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_EMIT, drm_savage_event_emit_t) -#define DRM_IOCTL_SAVAGE_BCI_EVENT_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_SAVAGE_BCI_EVENT_WAIT, drm_savage_event_wait_t) - -#define SAVAGE_DMA_PCI 1 -#define SAVAGE_DMA_AGP 3 -typedef struct drm_savage_init { - enum { - SAVAGE_INIT_BCI = 1, - SAVAGE_CLEANUP_BCI = 2 - } func; - unsigned int sarea_priv_offset; - - /* some parameters */ - unsigned int cob_size; - unsigned int bci_threshold_lo, bci_threshold_hi; - unsigned int dma_type; - - /* frame buffer layout */ - unsigned int fb_bpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - unsigned int depth_bpp; - unsigned int depth_offset, depth_pitch; - - /* local textures */ - unsigned int texture_offset; - unsigned int texture_size; - - /* physical locations of non-permanent maps */ - unsigned long status_offset; - unsigned long buffers_offset; - unsigned long agp_textures_offset; - unsigned long cmd_dma_offset; -} drm_savage_init_t; - -typedef union drm_savage_cmd_header drm_savage_cmd_header_t; -typedef struct drm_savage_cmdbuf { - /* command buffer in client's address space */ - drm_savage_cmd_header_t __user *cmd_addr; - unsigned int size; /* size of the command buffer in 64bit units */ - - unsigned int dma_idx; /* DMA buffer index to use */ - int discard; /* discard DMA buffer when done */ - /* vertex buffer in client's address space */ - unsigned int __user *vb_addr; - unsigned int vb_size; /* size of client vertex buffer in bytes */ - unsigned int vb_stride; /* stride of vertices in 32bit words */ - /* boxes in client's address space */ - struct drm_clip_rect __user *box_addr; - unsigned int nbox; /* number of clipping boxes */ -} drm_savage_cmdbuf_t; - -#define SAVAGE_WAIT_2D 0x1 /* wait for 2D idle before updating event tag */ -#define SAVAGE_WAIT_3D 0x2 /* wait for 3D idle before updating event tag */ -#define SAVAGE_WAIT_IRQ 0x4 /* emit or wait for IRQ, not implemented yet */ -typedef struct drm_savage_event { - unsigned int count; - unsigned int flags; -} drm_savage_event_emit_t, drm_savage_event_wait_t; - -/* Commands for the cmdbuf ioctl - */ -#define SAVAGE_CMD_STATE 0 /* a range of state registers */ -#define SAVAGE_CMD_DMA_PRIM 1 /* vertices from DMA buffer */ -#define SAVAGE_CMD_VB_PRIM 2 /* vertices from client vertex buffer */ -#define SAVAGE_CMD_DMA_IDX 3 /* indexed vertices from DMA buffer */ -#define SAVAGE_CMD_VB_IDX 4 /* indexed vertices client vertex buffer */ -#define SAVAGE_CMD_CLEAR 5 /* clear buffers */ -#define SAVAGE_CMD_SWAP 6 /* swap buffers */ - -/* Primitive types -*/ -#define SAVAGE_PRIM_TRILIST 0 /* triangle list */ -#define SAVAGE_PRIM_TRISTRIP 1 /* triangle strip */ -#define SAVAGE_PRIM_TRIFAN 2 /* triangle fan */ -#define SAVAGE_PRIM_TRILIST_201 3 /* reorder verts for correct flat - * shading on s3d */ - -/* Skip flags (vertex format) - */ -#define SAVAGE_SKIP_Z 0x01 -#define SAVAGE_SKIP_W 0x02 -#define SAVAGE_SKIP_C0 0x04 -#define SAVAGE_SKIP_C1 0x08 -#define SAVAGE_SKIP_S0 0x10 -#define SAVAGE_SKIP_T0 0x20 -#define SAVAGE_SKIP_ST0 0x30 -#define SAVAGE_SKIP_S1 0x40 -#define SAVAGE_SKIP_T1 0x80 -#define SAVAGE_SKIP_ST1 0xc0 -#define SAVAGE_SKIP_ALL_S3D 0x3f -#define SAVAGE_SKIP_ALL_S4 0xff - -/* Buffer names for clear command - */ -#define SAVAGE_FRONT 0x1 -#define SAVAGE_BACK 0x2 -#define SAVAGE_DEPTH 0x4 - -/* 64-bit command header - */ -union drm_savage_cmd_header { - struct { - unsigned char cmd; /* command */ - unsigned char pad0; - unsigned short pad1; - unsigned short pad2; - unsigned short pad3; - } cmd; /* generic */ - struct { - unsigned char cmd; - unsigned char global; /* need idle engine? */ - unsigned short count; /* number of consecutive registers */ - unsigned short start; /* first register */ - unsigned short pad3; - } state; /* SAVAGE_CMD_STATE */ - struct { - unsigned char cmd; - unsigned char prim; /* primitive type */ - unsigned short skip; /* vertex format (skip flags) */ - unsigned short count; /* number of vertices */ - unsigned short start; /* first vertex in DMA/vertex buffer */ - } prim; /* SAVAGE_CMD_DMA_PRIM, SAVAGE_CMD_VB_PRIM */ - struct { - unsigned char cmd; - unsigned char prim; - unsigned short skip; - unsigned short count; /* number of indices that follow */ - unsigned short pad3; - } idx; /* SAVAGE_CMD_DMA_IDX, SAVAGE_CMD_VB_IDX */ - struct { - unsigned char cmd; - unsigned char pad0; - unsigned short pad1; - unsigned int flags; - } clear0; /* SAVAGE_CMD_CLEAR */ - struct { - unsigned int mask; - unsigned int value; - } clear1; /* SAVAGE_CMD_CLEAR data */ -}; - -#if defined(__cplusplus) -} -#endif - -#endif -- cgit v1.2.3 From 20efabc2e80be1df79510b8be9ca004d3ce9be11 Mon Sep 17 00:00:00 2001 From: Cai Huoqing Date: Sat, 3 Dec 2022 18:22:56 +0800 Subject: drm: Remove the obsolete driver-sis Commit 399516ab0fee ("MAINTAINERS: Add a bunch of legacy (UMS) DRM drivers") marked sis driver obsolete 7 years ago. And the mesa UMD of this drm driver already in deprecated list in the link: https://docs.mesa3d.org/systems.html Silicon Integrated Systems->drivers/gpu/drm/sis It's time to remove this driver. Signed-off-by: Cai Huoqing Acked-by: Daniel Vetter Acked-by: Dave Airlie Acked-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20221203102502.3185-6-cai.huoqing@linux.dev --- drivers/gpu/drm/Kconfig | 9 -- drivers/gpu/drm/Makefile | 1 - drivers/gpu/drm/sis/Makefile | 10 -- drivers/gpu/drm/sis/sis_drv.c | 143 ----------------- drivers/gpu/drm/sis/sis_drv.h | 80 ---------- drivers/gpu/drm/sis/sis_mm.c | 363 ------------------------------------------ include/uapi/drm/sis_drm.h | 77 --------- 7 files changed, 683 deletions(-) delete mode 100644 drivers/gpu/drm/sis/Makefile delete mode 100644 drivers/gpu/drm/sis/sis_drv.c delete mode 100644 drivers/gpu/drm/sis/sis_drv.h delete mode 100644 drivers/gpu/drm/sis/sis_mm.c delete mode 100644 include/uapi/drm/sis_drm.h (limited to 'include') diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 14520cd4f7c0..9d6b17236937 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -405,15 +405,6 @@ config DRM_TDFX Choose this option if you have a 3dfx Banshee or Voodoo3 (or later), graphics card. If M is selected, the module will be called tdfx. -config DRM_SIS - tristate "SiS video cards" - depends on DRM && AGP - depends on FB_SIS || FB_SIS=n - help - Choose this option if you have a SiS 630 or compatible video - chipset. If M is selected the module will be called sis. AGP - support is required for this driver to work. - config DRM_VIA tristate "Via unichrome video cards" depends on DRM && PCI diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index dcc4801832ee..6698990ddedb 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -141,7 +141,6 @@ obj-$(CONFIG_DRM_KMB_DISPLAY) += kmb/ obj-$(CONFIG_DRM_MGAG200) += mgag200/ obj-$(CONFIG_DRM_V3D) += v3d/ obj-$(CONFIG_DRM_VC4) += vc4/ -obj-$(CONFIG_DRM_SIS) += sis/ obj-$(CONFIG_DRM_VMWGFX)+= vmwgfx/ obj-$(CONFIG_DRM_VIA) +=via/ obj-$(CONFIG_DRM_VGEM) += vgem/ diff --git a/drivers/gpu/drm/sis/Makefile b/drivers/gpu/drm/sis/Makefile deleted file mode 100644 index 02b0253fda93..000000000000 --- a/drivers/gpu/drm/sis/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the drm device driver. This driver provides support for the -# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. - -sis-y := sis_drv.o sis_mm.o - -obj-$(CONFIG_DRM_SIS) += sis.o - - diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c deleted file mode 100644 index 6173020a9bf5..000000000000 --- a/drivers/gpu/drm/sis/sis_drv.c +++ /dev/null @@ -1,143 +0,0 @@ -/* sis.c -- sis driver -*- linux-c -*- - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -#include -#include - -#include -#include -#include -#include - -#include "sis_drv.h" - -static struct pci_device_id pciidlist[] = { - sisdrv_PCI_IDS -}; - -static int sis_driver_load(struct drm_device *dev, unsigned long chipset) -{ - struct pci_dev *pdev = to_pci_dev(dev->dev); - drm_sis_private_t *dev_priv; - - pci_set_master(pdev); - - dev_priv = kzalloc(sizeof(drm_sis_private_t), GFP_KERNEL); - if (dev_priv == NULL) - return -ENOMEM; - - idr_init_base(&dev_priv->object_idr, 1); - dev->dev_private = (void *)dev_priv; - dev_priv->chipset = chipset; - - return 0; -} - -static void sis_driver_unload(struct drm_device *dev) -{ - drm_sis_private_t *dev_priv = dev->dev_private; - - idr_destroy(&dev_priv->object_idr); - - kfree(dev_priv); -} - -static const struct file_operations sis_driver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = drm_legacy_mmap, - .poll = drm_poll, - .compat_ioctl = drm_compat_ioctl, - .llseek = noop_llseek, -}; - -static int sis_driver_open(struct drm_device *dev, struct drm_file *file) -{ - struct sis_file_private *file_priv; - - DRM_DEBUG_DRIVER("\n"); - file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL); - if (!file_priv) - return -ENOMEM; - - file->driver_priv = file_priv; - - INIT_LIST_HEAD(&file_priv->obj_list); - - return 0; -} - -static void sis_driver_postclose(struct drm_device *dev, struct drm_file *file) -{ - struct sis_file_private *file_priv = file->driver_priv; - - kfree(file_priv); -} - -static struct drm_driver driver = { - .driver_features = DRIVER_USE_AGP | DRIVER_LEGACY, - .load = sis_driver_load, - .unload = sis_driver_unload, - .open = sis_driver_open, - .preclose = sis_reclaim_buffers_locked, - .postclose = sis_driver_postclose, - .dma_quiescent = sis_idle, - .lastclose = sis_lastclose, - .ioctls = sis_ioctls, - .fops = &sis_driver_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; - -static struct pci_driver sis_pci_driver = { - .name = DRIVER_NAME, - .id_table = pciidlist, -}; - -static int __init sis_init(void) -{ - driver.num_ioctls = sis_max_ioctl; - return drm_legacy_pci_init(&driver, &sis_pci_driver); -} - -static void __exit sis_exit(void) -{ - drm_legacy_pci_exit(&driver, &sis_pci_driver); -} - -module_init(sis_init); -module_exit(sis_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/sis/sis_drv.h b/drivers/gpu/drm/sis/sis_drv.h deleted file mode 100644 index 81339443b3b1..000000000000 --- a/drivers/gpu/drm/sis/sis_drv.h +++ /dev/null @@ -1,80 +0,0 @@ -/* sis_drv.h -- Private header for sis driver -*- linux-c -*- */ -/* - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - */ - -#ifndef _SIS_DRV_H_ -#define _SIS_DRV_H_ - -#include -#include -#include - -/* General customization: - */ - -#define DRIVER_AUTHOR "SIS, Tungsten Graphics" -#define DRIVER_NAME "sis" -#define DRIVER_DESC "SIS 300/630/540 and XGI V3XE/V5/V8" -#define DRIVER_DATE "20070626" -#define DRIVER_MAJOR 1 -#define DRIVER_MINOR 3 -#define DRIVER_PATCHLEVEL 0 - -enum sis_family { - SIS_OTHER = 0, - SIS_CHIP_315 = 1, -}; - -#define SIS_READ(reg) readl(((void __iomem *)dev_priv->mmio->handle) + (reg)) -#define SIS_WRITE(reg, val) writel(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) - -typedef struct drm_sis_private { - drm_local_map_t *mmio; - unsigned int idle_fault; - unsigned int chipset; - int vram_initialized; - int agp_initialized; - unsigned long vram_offset; - unsigned long agp_offset; - struct drm_mm vram_mm; - struct drm_mm agp_mm; - /** Mapping of userspace keys to mm objects */ - struct idr object_idr; -} drm_sis_private_t; - -struct sis_file_private { - struct list_head obj_list; -}; - -extern int sis_idle(struct drm_device *dev); -extern void sis_reclaim_buffers_locked(struct drm_device *dev, - struct drm_file *file_priv); -extern void sis_lastclose(struct drm_device *dev); - -extern const struct drm_ioctl_desc sis_ioctls[]; -extern int sis_max_ioctl; - -#endif diff --git a/drivers/gpu/drm/sis/sis_mm.c b/drivers/gpu/drm/sis/sis_mm.c deleted file mode 100644 index e51d4289a3d0..000000000000 --- a/drivers/gpu/drm/sis/sis_mm.c +++ /dev/null @@ -1,363 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * - **************************************************************************/ - -/* - * Authors: - * Thomas Hellström - */ - -#include