* (unknown), @ 2012-05-18 12:27 Sascha Hauer 2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer ` (2 more replies) 0 siblings, 3 replies; 42+ messages in thread From: Sascha Hauer @ 2012-05-18 12:27 UTC (permalink / raw) To: dri-devel; +Cc: linux-arm-kernel Hi All, The following adds a drm/kms driver for the Freescale i.MX LCDC controller. Most notable change to the last SDRM based version is that the SDRM layer has been removed and the driver now is purely i.MX specific. I hope that this is more acceptable now. Another change is that the probe is now devicetree based. For now I took the easy way out and only put an edid blob into the devicetree. I haven't documented the binding yet, I would add that when the rest is considered ok. Comments very welcome. Thanks Sascha ---------------------------------------------------------------- Sascha Hauer (2): DRM: add Freescale i.MX LCDC driver pcm038 lcdc support arch/arm/boot/dts/imx27-phytec-phycore.dts | 39 ++ arch/arm/boot/dts/imx27.dtsi | 7 + arch/arm/mach-imx/clock-imx27.c | 1 + drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/imx/Kconfig | 18 + drivers/gpu/drm/imx/Makefile | 8 + drivers/gpu/drm/imx/imx-drm-core.c | 745 ++++++++++++++++++++++++++++ drivers/gpu/drm/imx/imx-fb.c | 179 +++++++ drivers/gpu/drm/imx/imx-fbdev.c | 275 ++++++++++ drivers/gpu/drm/imx/imx-gem.c | 343 +++++++++++++ drivers/gpu/drm/imx/imx-lcdc-crtc.c | 517 +++++++++++++++++++ drivers/gpu/drm/imx/imx-parallel-display.c | 228 +++++++++ 13 files changed, 2363 insertions(+) create mode 100644 drivers/gpu/drm/imx/Kconfig create mode 100644 drivers/gpu/drm/imx/Makefile create mode 100644 drivers/gpu/drm/imx/imx-drm-core.c create mode 100644 drivers/gpu/drm/imx/imx-fb.c create mode 100644 drivers/gpu/drm/imx/imx-fbdev.c create mode 100644 drivers/gpu/drm/imx/imx-gem.c create mode 100644 drivers/gpu/drm/imx/imx-lcdc-crtc.c create mode 100644 drivers/gpu/drm/imx/imx-parallel-display.c ^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH 1/2] DRM: add Freescale i.MX LCDC driver 2012-05-18 12:27 (unknown), Sascha Hauer @ 2012-05-18 12:27 ` Sascha Hauer 2012-05-22 21:28 ` Rob Clark 2012-05-18 12:27 ` [PATCH 2/2] pcm038 lcdc support Sascha Hauer 2012-05-22 14:06 ` Lars-Peter Clausen 2 siblings, 1 reply; 42+ messages in thread From: Sascha Hauer @ 2012-05-18 12:27 UTC (permalink / raw) To: dri-devel; +Cc: Sascha Hauer, linux-arm-kernel Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/imx/Kconfig | 18 + drivers/gpu/drm/imx/Makefile | 8 + drivers/gpu/drm/imx/imx-drm-core.c | 745 ++++++++++++++++++++++++++++ drivers/gpu/drm/imx/imx-fb.c | 179 +++++++ drivers/gpu/drm/imx/imx-fbdev.c | 275 ++++++++++ drivers/gpu/drm/imx/imx-gem.c | 343 +++++++++++++ drivers/gpu/drm/imx/imx-lcdc-crtc.c | 517 +++++++++++++++++++ drivers/gpu/drm/imx/imx-parallel-display.c | 228 +++++++++ 10 files changed, 2316 insertions(+) create mode 100644 drivers/gpu/drm/imx/Kconfig create mode 100644 drivers/gpu/drm/imx/Makefile create mode 100644 drivers/gpu/drm/imx/imx-drm-core.c create mode 100644 drivers/gpu/drm/imx/imx-fb.c create mode 100644 drivers/gpu/drm/imx/imx-fbdev.c create mode 100644 drivers/gpu/drm/imx/imx-gem.c create mode 100644 drivers/gpu/drm/imx/imx-lcdc-crtc.c create mode 100644 drivers/gpu/drm/imx/imx-parallel-display.c diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index e354bc0..759502c 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -186,3 +186,5 @@ source "drivers/gpu/drm/vmwgfx/Kconfig" source "drivers/gpu/drm/gma500/Kconfig" source "drivers/gpu/drm/udl/Kconfig" + +source "drivers/gpu/drm/imx/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index c20da5b..6569d8d 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -42,4 +42,5 @@ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ obj-$(CONFIG_DRM_EXYNOS) +=exynos/ obj-$(CONFIG_DRM_GMA500) += gma500/ obj-$(CONFIG_DRM_UDL) += udl/ +obj-$(CONFIG_DRM_IMX) += imx/ obj-y += i2c/ diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig new file mode 100644 index 0000000..5fc3a44 --- /dev/null +++ b/drivers/gpu/drm/imx/Kconfig @@ -0,0 +1,18 @@ +config DRM_IMX + tristate "DRM Support for Freescale i.MX" + select DRM_KMS_HELPER + depends on DRM && ARCH_MXC + +config DRM_IMX_FB_HELPER + tristate "provide legacy framebuffer /dev/fb0" + depends on DRM_IMX + +config DRM_IMX_LCDC + tristate "DRM Support for Freescale i.MX1 and i.MX2" + depends on DRM_IMX + help + Choose this if you have a i.MX1, i.MX21, i.MX25 or i.MX27 processor. + +config DRM_IMX_PARALLEL_DISPLAY + tristate "Support for parallel displays" + depends on DRM_IMX diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile new file mode 100644 index 0000000..0f7c038 --- /dev/null +++ b/drivers/gpu/drm/imx/Makefile @@ -0,0 +1,8 @@ + +imxdrm-objs := imx-drm-core.o imx-fb.o imx-gem.o + +obj-$(CONFIG_DRM_IMX) += imxdrm.o + +obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += imx-parallel-display.o +obj-$(CONFIG_DRM_IMX_LCDC) += imx-lcdc-crtc.o +obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c new file mode 100644 index 0000000..29f5f10 --- /dev/null +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -0,0 +1,745 @@ +/* + * simple drm driver + * + * Copyright (C) 2011 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/device.h> +#include <linux/platform_device.h> +#include <drm/drmP.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_crtc_helper.h> +#include <linux/fb.h> +#include <asm/fb.h> +#include <linux/module.h> + +#include "imx-drm.h" + +#define MAX_CRTC 4 + +struct imx_drm_device { + struct drm_device *drm; + struct device *dev; + struct list_head crtc_list; + struct list_head encoder_list; + struct list_head connector_list; + struct mutex mutex; + int references; +}; + +struct imx_drm_crtc { + struct drm_crtc *crtc; + struct list_head list; + struct imx_drm_device *imxdrm; + int pipe; + struct drm_crtc_helper_funcs crtc_helper_funcs; + struct drm_crtc_funcs crtc_funcs; + struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; + struct module *owner; +}; + +struct imx_drm_encoder { + struct drm_encoder *encoder; + struct list_head list; + struct module *owner; +}; + +struct imx_drm_connector { + struct drm_connector *connector; + struct list_head list; + struct module *owner; +}; + +static int imx_drm_driver_firstopen(struct drm_device *drm) +{ + if (!imx_drm_device_get()) + return -EINVAL; + + return 0; +} + +static void imx_drm_driver_lastclose(struct drm_device *drm) +{ + imx_drm_device_put(); +} + +static int imx_drm_driver_unload(struct drm_device *drm) +{ + struct imx_drm_device *imxdrm = drm->dev_private; + + drm_mode_config_cleanup(imxdrm->drm); + drm_kms_helper_poll_fini(imxdrm->drm); + + return 0; +} + +/* + * We don't care at all for crtc numbers, but the core expects the + * crtcs to be numbered + */ +static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm, + int num) +{ + struct imx_drm_crtc *imx_drm_crtc; + + list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) + if (imx_drm_crtc->pipe == num) + return imx_drm_crtc; + return NULL; +} + +int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) +{ + return drm_vblank_get(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); +} +EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get); + +void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc) +{ + drm_vblank_put(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); +} +EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put); + +void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc) +{ + drm_handle_vblank(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); +} +EXPORT_SYMBOL_GPL(imx_drm_handle_vblank); + +static int imx_drm_enable_vblank(struct drm_device *drm, int crtc) +{ + struct imx_drm_device *imxdrm = drm->dev_private; + struct imx_drm_crtc *imx_drm_crtc; + int ret; + + imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc); + if (!imx_drm_crtc) + return -EINVAL; + + if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank) + return -ENOSYS; + + ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(imx_drm_crtc->crtc); + return ret; +} + +static void imx_drm_disable_vblank(struct drm_device *drm, int crtc) +{ + struct imx_drm_device *imxdrm = drm->dev_private; + struct imx_drm_crtc *imx_drm_crtc; + + imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc); + if (!imx_drm_crtc) + return; + + if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank) + return; + + imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc); +} + +static struct vm_operations_struct imx_drm_gem_vm_ops = { + .fault = imx_drm_gem_fault, + .open = drm_gem_vm_open, + .close = drm_gem_vm_close, +}; + +static const struct file_operations imx_drm_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = imx_drm_gem_mmap, + .poll = drm_poll, + .fasync = drm_fasync, + .read = drm_read, + .llseek = noop_llseek, +}; + +static struct imx_drm_device *imx_drm_device; + +static struct imx_drm_device *__imx_drm_device(void) +{ + return imx_drm_device; +} + +struct drm_device *imx_drm_device_get(void) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_encoder *enc; + struct imx_drm_connector *con; + struct imx_drm_crtc *crtc; + + mutex_lock(&imxdrm->mutex); + + list_for_each_entry(enc, &imxdrm->encoder_list, list) { + if (!try_module_get(enc->owner)) { + dev_err(imxdrm->dev, "could not get module %s\n", + module_name(enc->owner)); + goto unwind_enc; + } + } + + list_for_each_entry(con, &imxdrm->connector_list, list) { + if (!try_module_get(con->owner)) { + dev_err(imxdrm->dev, "could not get module %s\n", + module_name(con->owner)); + goto unwind_con; + } + } + + list_for_each_entry(crtc, &imxdrm->crtc_list, list) { + if (!try_module_get(crtc->owner)) { + dev_err(imxdrm->dev, "could not get module %s\n", + module_name(crtc->owner)); + goto unwind_crtc; + } + } + + imxdrm->references++; + + mutex_unlock(&imxdrm->mutex); + + return imx_drm_device->drm; + +unwind_crtc: + list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list) + module_put(crtc->owner); +unwind_con: + list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list) + module_put(con->owner); +unwind_enc: + list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list) + module_put(enc->owner); + + mutex_unlock(&imxdrm->mutex); + + return NULL; + +} +EXPORT_SYMBOL_GPL(imx_drm_device_get); + +void imx_drm_device_put(void) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_encoder *enc; + struct imx_drm_connector *con; + struct imx_drm_crtc *crtc; + + mutex_lock(&imxdrm->mutex); + + list_for_each_entry(crtc, &imxdrm->crtc_list, list) + module_put(crtc->owner); + + list_for_each_entry(con, &imxdrm->connector_list, list) + module_put(con->owner); + + list_for_each_entry(enc, &imxdrm->encoder_list, list) + module_put(enc->owner); + + imxdrm->references--; + + mutex_unlock(&imxdrm->mutex); +} +EXPORT_SYMBOL_GPL(imx_drm_device_put); + +static int drm_mode_group_reinit(struct drm_device *dev) +{ + struct drm_mode_group *group = &dev->primary->mode_group; + uint32_t *id_list = group->id_list; + int ret; + + ret = drm_mode_group_init_legacy_group(dev, group); + if (ret < 0) + return ret; + + kfree(id_list); + return 0; +} + +/* + * register an encoder to the drm core + */ +static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder, + imx_drm_encoder->encoder->funcs, + DRM_MODE_ENCODER_TMDS); + + drm_mode_group_reinit(imxdrm->drm); + + return 0; +} + +/* + * unregister an encoder from the drm core + */ +static void imx_drm_encoder_unregister(struct imx_drm_encoder *imx_drm_encoder) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + drm_encoder_cleanup(imx_drm_encoder->encoder); + + drm_mode_group_reinit(imxdrm->drm); +} + +/* + * register a connector to the drm core + */ +static int imx_drm_connector_register(struct imx_drm_connector *imx_drm_connector) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + int ret; + + drm_connector_init(imxdrm->drm, imx_drm_connector->connector, + imx_drm_connector->connector->funcs, + DRM_MODE_CONNECTOR_VGA); + drm_mode_group_reinit(imxdrm->drm); + ret = drm_sysfs_connector_add(imx_drm_connector->connector); + if (ret) + goto err; + + return 0; +err: + + return ret; +} + +/* + * unregister a connector from the drm core + */ +static void imx_drm_connector_unregister(struct imx_drm_connector *imx_drm_connector) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + drm_sysfs_connector_remove(imx_drm_connector->connector); + drm_connector_cleanup(imx_drm_connector->connector); + + drm_mode_group_reinit(imxdrm->drm); +} + +/* + * register a crtc to the drm core + */ +static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + int ret; + + drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc, &imx_drm_crtc->crtc_funcs); + ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256); + if (ret) + return ret; + + drm_crtc_helper_add(imx_drm_crtc->crtc, &imx_drm_crtc->crtc_helper_funcs); + + return 0; +} + +/* + * Called by the CRTC driver when all CRTCs are registered. This + * puts all the pieces together and initializes the driver. + * Once this is called no more CRTCs can be registered since + * the drm core has hardcoded the number of crtcs in several + * places. + */ +static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + int ret; + + imxdrm->drm = drm; + + drm->dev_private = imxdrm; + + /* + * enable drm irq mode. + * - with irq_enabled = 1, we can use the vblank feature. + * + * P.S. note that we wouldn't use drm irq handler but + * just specific driver own one instead because + * drm framework supports only one irq handler and + * drivers can well take care of their interrupts + */ + drm->irq_enabled = 1; + + drm_mode_config_init(drm); + imx_drm_mode_config_init(drm); + + mutex_lock(&imxdrm->mutex); + + drm_kms_helper_poll_init(imxdrm->drm); + + /* setup the grouping for the legacy output */ + ret = drm_mode_group_init_legacy_group(imxdrm->drm, + &imxdrm->drm->primary->mode_group); + if (ret) + goto err_init; + + ret = drm_vblank_init(imxdrm->drm, MAX_CRTC); + if (ret) + goto err_init; + + /* + * with vblank_disable_allowed = 1, vblank interrupt will be disabled + * by drm timer once a current process gives up ownership of + * vblank event.(after drm_vblank_put function is called) + */ + imxdrm->drm->vblank_disable_allowed = 1; + + ret = 0; + +err_init: + mutex_unlock(&imxdrm->mutex); + + return ret; +} + +/* + * imx_drm_add_crtc - add a new crtc + * + * The return value if !NULL is a cookie for the caller to pass to + * imx_drm_remove_crtc later. + */ +int imx_drm_add_crtc(struct drm_crtc *crtc, + struct imx_drm_crtc **new_crtc, + const struct drm_crtc_funcs *crtc_funcs, + const struct drm_crtc_helper_funcs *crtc_helper_funcs, + const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs, + struct module *owner) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_crtc *imx_drm_crtc; + int ret; + + mutex_lock(&imxdrm->mutex); + + if (imxdrm->references) { + ret = -EBUSY; + goto err_busy; + } + + imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL); + if (!imx_drm_crtc) { + ret = -ENOMEM; + goto err_alloc; + } + + imx_drm_crtc->crtc_funcs = *crtc_funcs; + imx_drm_crtc->crtc_helper_funcs = *crtc_helper_funcs; + imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; + + WARN_ON(crtc_funcs->set_config); + WARN_ON(crtc_funcs->destroy); + + imx_drm_crtc->crtc_funcs.set_config = drm_crtc_helper_set_config; + imx_drm_crtc->crtc_funcs.destroy = drm_crtc_cleanup; + + imx_drm_crtc->crtc = crtc; + imx_drm_crtc->imxdrm = imxdrm; + + imx_drm_crtc->owner = owner; + + list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list); + + *new_crtc = imx_drm_crtc; + + ret = imx_drm_crtc_register(imx_drm_crtc); + if (ret) + goto err_register; + + mutex_unlock(&imxdrm->mutex); + + return 0; + +err_register: + kfree(imx_drm_crtc); +err_alloc: +err_busy: + mutex_unlock(&imxdrm->mutex); + return ret; +} +EXPORT_SYMBOL_GPL(imx_drm_add_crtc); + +/* + * imx_drm_remove_crtc - remove a crtc + */ +int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc) +{ + struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm; + + mutex_lock(&imxdrm->mutex); + + drm_crtc_cleanup(imx_drm_crtc->crtc); + + list_del(&imx_drm_crtc->list); + + mutex_unlock(&imxdrm->mutex); + + kfree(imx_drm_crtc); + + return 0; +} +EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); + +/* + * imx_drm_add_encoder - add a new encoder + */ +int imx_drm_add_encoder(struct drm_encoder *encoder, + struct imx_drm_encoder **newenc, struct module *owner) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_encoder *imx_drm_encoder; + int ret; + + mutex_lock(&imxdrm->mutex); + + if (imxdrm->references) { + ret = -EBUSY; + goto err_busy; + } + + imx_drm_encoder = kzalloc(sizeof(struct imx_drm_encoder), GFP_KERNEL); + if (!imx_drm_encoder) { + ret = -ENOMEM; + goto err_alloc; + } + + imx_drm_encoder->encoder = encoder; + imx_drm_encoder->owner = owner; + + ret = imx_drm_encoder_register(imx_drm_encoder); + if (ret) { + kfree(imx_drm_encoder); + ret = -ENOMEM; + goto err_register; + } + + list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list); + + *newenc = imx_drm_encoder; + + mutex_unlock(&imxdrm->mutex); + + return 0; + +err_register: + kfree(imx_drm_encoder); +err_alloc: +err_busy: + mutex_unlock(&imxdrm->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(imx_drm_add_encoder); + +/* + * imx_drm_remove_encoder - remove an encoder + */ +int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + mutex_lock(&imxdrm->mutex); + + imx_drm_encoder_unregister(imx_drm_encoder); + + list_del(&imx_drm_encoder->list); + + mutex_unlock(&imxdrm->mutex); + + kfree(imx_drm_encoder); + + return 0; +} +EXPORT_SYMBOL_GPL(imx_drm_remove_encoder); + +/* + * imx_drm_add_connector - add a connector + */ +int imx_drm_add_connector(struct drm_connector *connector, + struct imx_drm_connector **new_con, + struct module *owner) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + struct imx_drm_connector *imx_drm_connector; + int ret; + + mutex_lock(&imxdrm->mutex); + + if (imxdrm->references) { + ret = -EBUSY; + goto err_busy; + } + + imx_drm_connector = kzalloc(sizeof(struct imx_drm_connector), GFP_KERNEL); + if (!imx_drm_connector) { + ret = -ENOMEM; + goto err_alloc; + } + + imx_drm_connector->connector = connector; + imx_drm_connector->owner = owner; + + ret = imx_drm_connector_register(imx_drm_connector); + if (ret) + goto err_register; + + list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list); + + *new_con = imx_drm_connector; + + mutex_unlock(&imxdrm->mutex); + + return 0; + +err_register: + kfree(imx_drm_connector); +err_alloc: +err_busy: + mutex_unlock(&imxdrm->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(imx_drm_add_connector); + +/* + * imx_drm_remove_connector - remove a connector + */ +int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector) +{ + struct imx_drm_device *imxdrm = __imx_drm_device(); + + mutex_lock(&imxdrm->mutex); + + imx_drm_connector_unregister(imx_drm_connector); + + list_del(&imx_drm_connector->list); + + mutex_unlock(&imxdrm->mutex); + + kfree(imx_drm_connector); + + return 0; +} +EXPORT_SYMBOL_GPL(imx_drm_remove_connector); + +static struct drm_ioctl_desc imx_drm_ioctls[] = { + /* none so far */ +}; + +static struct drm_driver imx_drm_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM, + .load = imx_drm_driver_load, + .unload = imx_drm_driver_unload, + .firstopen = imx_drm_driver_firstopen, + .lastclose = imx_drm_driver_lastclose, + .gem_free_object = imx_drm_gem_free_object, + .gem_vm_ops = &imx_drm_gem_vm_ops, + .dumb_create = imx_drm_gem_dumb_create, + .dumb_map_offset = imx_drm_gem_dumb_map_offset, + .dumb_destroy = imx_drm_gem_dumb_destroy, + + .get_vblank_counter = drm_vblank_count, + .enable_vblank = imx_drm_enable_vblank, + .disable_vblank = imx_drm_disable_vblank, + .reclaim_buffers = drm_core_reclaim_buffers, + .ioctls = imx_drm_ioctls, + .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), + .fops = &imx_drm_driver_fops, + .name = "imx-drm", + .desc = "i.MX DRM graphics", + .date = "20120507", + .major = 1, + .minor = 0, + .patchlevel = 0, +}; + +static int imx_drm_platform_probe(struct platform_device *pdev) +{ + imx_drm_device->dev = &pdev->dev; + + return drm_platform_init(&imx_drm_driver, pdev); +} + +static int imx_drm_platform_remove(struct platform_device *pdev) +{ + drm_platform_exit(&imx_drm_driver, pdev); + + return 0; +} + +static struct platform_driver imx_drm_pdrv = { + .probe = imx_drm_platform_probe, + .remove = __devexit_p(imx_drm_platform_remove), + .driver = { + .owner = THIS_MODULE, + .name = "imx-drm", + }, +}; + +static struct platform_device *imx_drm_pdev; + +static int __init imx_drm_init(void) +{ + int ret; + + imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL); + if (!imx_drm_device) + return -ENOMEM; + + mutex_init(&imx_drm_device->mutex); + INIT_LIST_HEAD(&imx_drm_device->crtc_list); + INIT_LIST_HEAD(&imx_drm_device->connector_list); + INIT_LIST_HEAD(&imx_drm_device->encoder_list); + + imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0); + if (!imx_drm_pdev) { + ret = -EINVAL; + goto err_pdev; + } + + imx_drm_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32), + + ret = platform_driver_register(&imx_drm_pdrv); + if (ret) + goto err_pdrv; + + return 0; + +err_pdev: + kfree(imx_drm_device); +err_pdrv: + platform_device_unregister(imx_drm_pdev); + + return ret; +} + +static void __exit imx_drm_exit(void) +{ + DRM_DEBUG_DRIVER("%s\n", __FILE__); + + platform_device_unregister(imx_drm_pdev); + platform_driver_unregister(&imx_drm_pdrv); + + kfree(imx_drm_device); +} + +module_init(imx_drm_init); +module_exit(imx_drm_exit); + +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); +MODULE_DESCRIPTION("i.MX drm driver core"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/imx/imx-fb.c b/drivers/gpu/drm/imx/imx-fb.c new file mode 100644 index 0000000..5a08c86 --- /dev/null +++ b/drivers/gpu/drm/imx/imx-fb.c @@ -0,0 +1,179 @@ +/* + * i.MX drm driver + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * Based on Samsung Exynos code + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <linux/module.h> +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_crtc_helper.h> + +#include "imx-drm.h" + +#define to_imx_drm_fb(x) container_of(x, struct imx_drm_fb, fb) + +/* + * imx specific framebuffer structure. + * + * @fb: drm framebuffer obejct. + * @imx_drm_gem_obj: drm ec specific gem object containing a gem object. + * @entry: pointer to ec drm buffer entry object. + * - containing only the information to physically continuous memory + * region allocated at default framebuffer creation. + */ +struct imx_drm_fb { + struct drm_framebuffer fb; + struct imx_drm_gem_obj *imx_drm_gem_obj; + struct imx_drm_buf_entry *entry; +}; + +static void imx_drm_fb_destroy(struct drm_framebuffer *fb) +{ + struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb); + + drm_framebuffer_cleanup(fb); + + /* + * default framebuffer has no gem object so + * a buffer of the default framebuffer should be released at here. + */ + if (!imx_drm_fb->imx_drm_gem_obj && imx_drm_fb->entry) + imx_drm_buf_destroy(fb->dev, imx_drm_fb->entry); + + kfree(imx_drm_fb); +} + +static int imx_drm_fb_create_handle(struct drm_framebuffer *fb, + struct drm_file *file_priv, unsigned int *handle) +{ + struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb); + + return drm_gem_handle_create(file_priv, + &imx_drm_fb->imx_drm_gem_obj->base, handle); +} + +static struct drm_framebuffer_funcs imx_drm_fb_funcs = { + .destroy = imx_drm_fb_destroy, + .create_handle = imx_drm_fb_create_handle, +}; + +static struct drm_framebuffer *imx_drm_fb_create(struct drm_device *dev, + struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) +{ + struct imx_drm_fb *imx_drm_fb; + struct drm_framebuffer *fb; + struct drm_gem_object *obj; + unsigned int size; + int ret; + u32 bpp, depth; + + drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); + + mode_cmd->pitches[0] = max(mode_cmd->pitches[0], + mode_cmd->width * (bpp >> 3)); + + dev_dbg(dev->dev, "drm fb create(%dx%d)\n", + mode_cmd->width, mode_cmd->height); + + imx_drm_fb = kzalloc(sizeof(*imx_drm_fb), GFP_KERNEL); + if (!imx_drm_fb) { + dev_err(dev->dev, "failed to allocate drm framebuffer.\n"); + return ERR_PTR(-ENOMEM); + } + + fb = &imx_drm_fb->fb; + ret = drm_framebuffer_init(dev, fb, &imx_drm_fb_funcs); + if (ret) { + dev_err(dev->dev, "failed to initialize framebuffer.\n"); + goto err_init; + } + + dev_dbg(dev->dev, "create: fb id: %d\n", fb->base.id); + + size = mode_cmd->pitches[0] * mode_cmd->height; + + /* + * without file_priv we are called from imx_drm_fbdev_create in which + * case we only create a framebuffer without a handle. + */ + if (!file_priv) { + struct imx_drm_buf_entry *entry; + + entry = imx_drm_buf_create(dev, size); + if (IS_ERR(entry)) { + ret = PTR_ERR(entry); + goto err_buffer; + } + + imx_drm_fb->entry = entry; + } else { + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); + if (!obj) { + ret = -EINVAL; + goto err_buffer; + } + + imx_drm_fb->imx_drm_gem_obj = to_imx_drm_gem_obj(obj); + + drm_gem_object_unreference_unlocked(obj); + + imx_drm_fb->entry = imx_drm_fb->imx_drm_gem_obj->entry; + } + + drm_helper_mode_fill_fb_struct(fb, mode_cmd); + + return fb; + +err_buffer: + drm_framebuffer_cleanup(fb); + +err_init: + kfree(imx_drm_fb); + + return ERR_PTR(ret); +} + +struct imx_drm_buf_entry *imx_drm_fb_get_buf(struct drm_framebuffer *fb) +{ + struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb); + struct imx_drm_buf_entry *entry; + + entry = imx_drm_fb->entry; + + return entry; +} +EXPORT_SYMBOL_GPL(imx_drm_fb_get_buf); + +static struct drm_mode_config_funcs imx_drm_mode_config_funcs = { + .fb_create = imx_drm_fb_create, +}; + +void imx_drm_mode_config_init(struct drm_device *dev) +{ + dev->mode_config.min_width = 64; + dev->mode_config.min_height = 64; + + /* + * set max width and height as default value(4096x4096). + * this value would be used to check framebuffer size limitation + * at drm_mode_addfb(). + */ + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; + + dev->mode_config.funcs = &imx_drm_mode_config_funcs; +} diff --git a/drivers/gpu/drm/imx/imx-fbdev.c b/drivers/gpu/drm/imx/imx-fbdev.c new file mode 100644 index 0000000..f038797 --- /dev/null +++ b/drivers/gpu/drm/imx/imx-fbdev.c @@ -0,0 +1,275 @@ +/* + * i.MX drm driver + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * Based on Samsung Exynos code + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <linux/module.h> +#include <drm/drmP.h> +#include <drm/drm_crtc.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_crtc_helper.h> + +#include "imx-drm.h" + +#define MAX_CONNECTOR 4 +#define PREFERRED_BPP 16 + +static struct fb_ops imx_drm_fb_ops = { + .owner = THIS_MODULE, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_blank = drm_fb_helper_blank, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_setcmap = drm_fb_helper_setcmap, +}; + +static int imx_drm_fbdev_update(struct drm_fb_helper *helper, + struct drm_framebuffer *fb, + unsigned int fb_width, + unsigned int fb_height) +{ + struct fb_info *fbi = helper->fbdev; + struct drm_device *drm = helper->dev; + struct imx_drm_buf_entry *entry; + unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3); + unsigned long offset; + + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); + drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height); + + entry = imx_drm_fb_get_buf(fb); + if (!entry) { + dev_dbg(drm->dev, "entry is null.\n"); + return -EFAULT; + } + + offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); + offset += fbi->var.yoffset * fb->pitches[0]; + + drm->mode_config.fb_base = entry->paddr; + fbi->screen_base = entry->vaddr + offset; + fbi->fix.smem_start = entry->paddr + offset; + fbi->screen_size = size; + fbi->fix.smem_len = size; + fbi->flags |= FBINFO_CAN_FORCE_OUTPUT; + + return 0; +} + +static int imx_drm_fbdev_create(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct drm_device *drm = helper->dev; + struct fb_info *fbi; + struct drm_framebuffer *fb; + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; + struct platform_device *pdev = drm->platformdev; + int ret; + + dev_dbg(drm->dev, "surface width(%d), height(%d) and bpp(%d\n", + sizes->surface_width, sizes->surface_height, + sizes->surface_bpp); + + mode_cmd.width = sizes->surface_width; + mode_cmd.height = sizes->surface_height; + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + mutex_lock(&drm->struct_mutex); + + fbi = framebuffer_alloc(0, &pdev->dev); + if (!fbi) { + ret = -ENOMEM; + goto err_fb_alloc; + } + + fb = drm->mode_config.funcs->fb_create(drm, NULL, &mode_cmd); + if (IS_ERR(fb)) { + dev_err(drm->dev, "failed to create drm framebuffer.\n"); + ret = PTR_ERR(fb); + goto err_fb_create; + } + + helper->fb = fb; + helper->fbdev = fbi; + + fbi->par = helper; + fbi->flags = FBINFO_FLAG_DEFAULT; + fbi->fbops = &imx_drm_fb_ops; + + ret = fb_alloc_cmap(&fbi->cmap, 256, 0); + if (ret) + goto err_alloc_cmap; + + ret = imx_drm_fbdev_update(helper, helper->fb, sizes->fb_width, + sizes->fb_height); + if (ret) + goto err_fbdev_update; + + mutex_unlock(&drm->struct_mutex); + + return 0; + +err_fbdev_update: + fb_dealloc_cmap(&fbi->cmap); + +err_alloc_cmap: + fb->funcs->destroy(fb); + +err_fb_create: + framebuffer_release(fbi); + +err_fb_alloc: + mutex_unlock(&drm->struct_mutex); + + return ret; +} + +static int imx_drm_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + int ret; + + BUG_ON(helper->fb); + + ret = imx_drm_fbdev_create(helper, sizes); + if (ret) { + dev_err(helper->dev->dev, "creating fbdev failed with %d\n", ret); + return ret; + } + + /* + * fb_helper expects a value more than 1 if succeed + * because register_framebuffer() should be called. + */ + return 1; +} + +static struct drm_fb_helper_funcs imx_drm_fb_helper_funcs = { + .fb_probe = imx_drm_fbdev_probe, +}; + +static struct drm_fb_helper *imx_drm_fbdev_init(struct drm_device *drm, + int preferred_bpp) +{ + struct drm_fb_helper *helper; + unsigned int num_crtc; + int ret; + + helper = kzalloc(sizeof(*helper), GFP_KERNEL); + if (!helper) + return NULL; + + helper->funcs = &imx_drm_fb_helper_funcs; + + num_crtc = drm->mode_config.num_crtc; + + ret = drm_fb_helper_init(drm, helper, num_crtc, MAX_CONNECTOR); + if (ret) { + dev_err(drm->dev, "initializing drm fb helper failed with %d\n", + ret); + goto err_init; + } + + ret = drm_fb_helper_single_add_all_connectors(helper); + if (ret) { + dev_err(drm->dev, "registering drm_fb_helper_connector failed with %d\n", + ret); + goto err_setup; + + } + + ret = drm_fb_helper_initial_config(helper, preferred_bpp); + if (ret) { + dev_err(drm->dev, "initial config failed with %d\n", ret); + goto err_setup; + } + + return helper; + +err_setup: + drm_fb_helper_fini(helper); + +err_init: + kfree(helper); + + return NULL; +} + +static void imx_drm_fbdev_fini(struct drm_fb_helper *helper) +{ + struct imx_drm_buf_entry *entry; + + if (helper->fbdev) { + struct fb_info *info; + int ret; + + info = helper->fbdev; + ret = unregister_framebuffer(info); + if (ret) + dev_err(helper->dev->dev, "unregister_framebuffer failed with %d\n", + ret); + + if (info->cmap.len) + fb_dealloc_cmap(&info->cmap); + + entry = imx_drm_fb_get_buf(helper->fb); + + imx_drm_buf_destroy(helper->dev, entry); + + framebuffer_release(info); + } + + drm_fb_helper_fini(helper); + + kfree(helper); +} + +static struct drm_fb_helper *imx_fb_helper; + +static int __init imx_fb_helper_init(void) +{ + struct drm_device *drm = imx_drm_device_get(); + int ret; + + if (!drm) + return -EINVAL; + + imx_fb_helper = imx_drm_fbdev_init(drm, PREFERRED_BPP); + if (!imx_fb_helper) { + imx_drm_device_put(); + return -EINVAL; + } + + return 0; +} + +static void __exit imx_fb_helper_exit(void) +{ + imx_drm_fbdev_fini(imx_fb_helper); + imx_drm_device_put(); +} + +late_initcall(imx_fb_helper_init); +module_exit(imx_fb_helper_exit); + +MODULE_DESCRIPTION("Freescale i.MX legacy fb driver"); +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/imx/imx-gem.c b/drivers/gpu/drm/imx/imx-gem.c new file mode 100644 index 0000000..b0866fb --- /dev/null +++ b/drivers/gpu/drm/imx/imx-gem.c @@ -0,0 +1,343 @@ +/* + * i.MX drm driver + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * Based on Samsung Exynos code + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <drm/drmP.h> +#include <drm/drm.h> +#include <drm/drm_crtc_helper.h> + +#include "imx-drm.h" + +static int lowlevel_buffer_allocate(struct drm_device *drm, + struct imx_drm_buf_entry *entry) +{ + entry->vaddr = dma_alloc_writecombine(drm->dev, entry->size, + (dma_addr_t *)&entry->paddr, GFP_KERNEL); + if (!entry->vaddr) { + dev_err(drm->dev, "failed to allocate buffer.\n"); + return -ENOMEM; + } + + dev_dbg(drm->dev, "allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n", + (unsigned int)entry->vaddr, entry->paddr, entry->size); + + return 0; +} + +static void lowlevel_buffer_free(struct drm_device *drm, + struct imx_drm_buf_entry *entry) +{ + dma_free_writecombine(drm->dev, entry->size, entry->vaddr, + entry->paddr); +} + +struct imx_drm_buf_entry *imx_drm_buf_create(struct drm_device *drm, + unsigned int size) +{ + struct imx_drm_buf_entry *entry; + + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return ERR_PTR(-ENOMEM); + + entry->size = size; + + /* + * allocate memory region with size and set the memory information + * to vaddr and paddr of a entry object. + */ + if (lowlevel_buffer_allocate(drm, entry) < 0) { + kfree(entry); + return ERR_PTR(-ENOMEM); + } + + return entry; +} + +void imx_drm_buf_destroy(struct drm_device *drm, + struct imx_drm_buf_entry *entry) +{ + lowlevel_buffer_free(drm, entry); + + kfree(entry); + entry = NULL; +} +EXPORT_SYMBOL_GPL(imx_drm_buf_destroy); + +static unsigned int convert_to_vm_err_msg(int msg) +{ + unsigned int out_msg; + + switch (msg) { + case 0: + case -ERESTARTSYS: + case -EINTR: + out_msg = VM_FAULT_NOPAGE; + break; + + case -ENOMEM: + out_msg = VM_FAULT_OOM; + break; + + default: + out_msg = VM_FAULT_SIGBUS; + break; + } + + return out_msg; +} + +static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) +{ + return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; +} + +static struct imx_drm_gem_obj *imx_drm_gem_create(struct drm_device *drm, + unsigned int size) +{ + struct imx_drm_gem_obj *imx_drm_gem_obj; + struct imx_drm_buf_entry *entry; + struct drm_gem_object *obj; + int ret; + + size = roundup(size, PAGE_SIZE); + + imx_drm_gem_obj = kzalloc(sizeof(*imx_drm_gem_obj), GFP_KERNEL); + if (!imx_drm_gem_obj) + return ERR_PTR(-ENOMEM); + + /* allocate the new buffer object and memory region. */ + entry = imx_drm_buf_create(drm, size); + if (!entry) { + ret = -ENOMEM; + goto err_alloc; + } + + imx_drm_gem_obj->entry = entry; + + obj = &imx_drm_gem_obj->base; + + ret = drm_gem_object_init(drm, obj, size); + if (ret) { + dev_err(drm->dev, "initializing GEM object failed with %d\n", ret); + goto err_obj_init; + } + + ret = drm_gem_create_mmap_offset(obj); + if (ret) { + dev_err(drm->dev, "creating mmap offset failed with %d\n", ret); + goto err_create_mmap_offset; + } + + return imx_drm_gem_obj; + +err_create_mmap_offset: + drm_gem_object_release(obj); + +err_obj_init: + imx_drm_buf_destroy(drm, imx_drm_gem_obj->entry); + +err_alloc: + kfree(imx_drm_gem_obj); + + return ERR_PTR(ret); +} + +static struct imx_drm_gem_obj *imx_drm_gem_create_with_handle(struct drm_file *file_priv, + struct drm_device *drm, unsigned int size, + unsigned int *handle) +{ + struct imx_drm_gem_obj *imx_drm_gem_obj; + struct drm_gem_object *obj; + int ret; + + imx_drm_gem_obj = imx_drm_gem_create(drm, size); + if (IS_ERR(imx_drm_gem_obj)) + return imx_drm_gem_obj; + + obj = &imx_drm_gem_obj->base; + + /* + * allocate a id of idr table where the obj is registered + * and handle has the id what user can see. + */ + ret = drm_gem_handle_create(file_priv, obj, handle); + if (ret) + goto err_handle_create; + + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_unreference_unlocked(obj); + + return imx_drm_gem_obj; + +err_handle_create: + imx_drm_gem_free_object(obj); + + return ERR_PTR(ret); +} + +static int imx_drm_gem_mmap_buffer(struct file *filp, + struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = filp->private_data; + struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj); + struct imx_drm_buf_entry *entry; + unsigned long pfn, vm_size; + + vma->vm_flags |= VM_IO | VM_RESERVED; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_file = filp; + + vm_size = vma->vm_end - vma->vm_start; + /* + * an entry contains information to physically continuous memory + * allocated by user request or at framebuffer creation. + */ + entry = imx_drm_gem_obj->entry; + + /* check if user-requested size is valid. */ + if (vm_size > entry->size) + return -EINVAL; + + /* + * get page frame number to physical memory to be mapped + * to user space. + */ + pfn = imx_drm_gem_obj->entry->paddr >> PAGE_SHIFT; + + if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size, + vma->vm_page_prot)) { + dev_err(obj->dev->dev, "failed to remap pfn range.\n"); + return -EAGAIN; + } + + return 0; +} + +static const struct file_operations imx_drm_gem_fops = { + .mmap = imx_drm_gem_mmap_buffer, +}; + +int imx_drm_gem_init_object(struct drm_gem_object *obj) +{ + return 0; +} + +void imx_drm_gem_free_object(struct drm_gem_object *gem_obj) +{ + struct imx_drm_gem_obj *imx_drm_gem_obj; + + if (gem_obj->map_list.map) + drm_gem_free_mmap_offset(gem_obj); + + drm_gem_object_release(gem_obj); + + imx_drm_gem_obj = to_imx_drm_gem_obj(gem_obj); + + imx_drm_buf_destroy(gem_obj->dev, imx_drm_gem_obj->entry); + + kfree(imx_drm_gem_obj); +} + +int imx_drm_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, struct drm_mode_create_dumb *args) +{ + struct imx_drm_gem_obj *imx_drm_gem_obj; + + /* FIXME: This should be configured by the crtc driver */ + args->pitch = args->width * args->bpp >> 3; + args->size = args->pitch * args->height; + + imx_drm_gem_obj = imx_drm_gem_create_with_handle(file_priv, dev, args->size, + &args->handle); + if (IS_ERR(imx_drm_gem_obj)) + return PTR_ERR(imx_drm_gem_obj); + + return 0; +} + +int imx_drm_gem_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *drm, uint32_t handle, uint64_t *offset) +{ + struct imx_drm_gem_obj *imx_drm_gem_obj; + struct drm_gem_object *obj; + + mutex_lock(&drm->struct_mutex); + + obj = drm_gem_object_lookup(drm, file_priv, handle); + if (!obj) { + dev_err(drm->dev, "failed to lookup gem object\n"); + mutex_unlock(&drm->struct_mutex); + return -EINVAL; + } + + imx_drm_gem_obj = to_imx_drm_gem_obj(obj); + + *offset = get_gem_mmap_offset(&imx_drm_gem_obj->base); + + drm_gem_object_unreference(obj); + + mutex_unlock(&drm->struct_mutex); + + return 0; +} + +int imx_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct drm_gem_object *obj = vma->vm_private_data; + struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj); + struct drm_device *dev = obj->dev; + unsigned long pfn; + pgoff_t page_offset; + int ret; + + page_offset = ((unsigned long)vmf->virtual_address - + vma->vm_start) >> PAGE_SHIFT; + + mutex_lock(&dev->struct_mutex); + + pfn = (imx_drm_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset; + + ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); + + mutex_unlock(&dev->struct_mutex); + + return convert_to_vm_err_msg(ret); +} + +int imx_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) +{ + int ret; + + ret = drm_gem_mmap(filp, vma); + if (ret) + return ret; + + vma->vm_flags &= ~VM_PFNMAP; + vma->vm_flags |= VM_MIXEDMAP; + + return ret; +} + + +int imx_drm_gem_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, unsigned int handle) +{ + return drm_gem_handle_delete(file_priv, handle); +} diff --git a/drivers/gpu/drm/imx/imx-lcdc-crtc.c b/drivers/gpu/drm/imx/imx-lcdc-crtc.c new file mode 100644 index 0000000..e77c015 --- /dev/null +++ b/drivers/gpu/drm/imx/imx-lcdc-crtc.c @@ -0,0 +1,517 @@ +/* + * i.MX LCDC crtc driver + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <linux/device.h> +#include <linux/platform_device.h> +#include <drm/drmP.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_crtc_helper.h> +#include <linux/fb.h> +#include <linux/clk.h> +#include <asm/fb.h> +#include <linux/module.h> +#include <mach/hardware.h> +#include <mach/imxfb.h> +#include <generated/mach-types.h> + +#include "imx-drm.h" + +#define LCDC_SSA 0x00 +#define LCDC_SIZE 0x04 +#define LCDC_VPW 0x08 +#define LCDC_CPOS 0x0C +#define LCDC_LCWHB 0x10 +#define LCDC_LCHCC 0x14 +#define LCDC_PCR 0x18 +#define LCDC_HCR 0x1C +#define LCDC_VCR 0x20 +#define LCDC_POS 0x24 +#define LCDC_LSCR1 0x28 +#define LCDC_PWMR 0x2C +#define LCDC_DMACR 0x30 +#define LCDC_RMCR 0x34 +#define LCDC_LCDICR 0x38 +#define LCDC_LIER 0x3c +#define LCDC_LISR 0x40 + +#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) + +#define YMAX_MASK (cpu_is_mx1() ? 0x1ff : 0x3ff) +#define SIZE_YMAX(y) ((y) & YMAX_MASK) + +#define VPW_VPW(x) ((x) & 0x3ff) + +#define HCR_H_WIDTH(x) (((x) & 0x3f) << 26) +#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8) +#define HCR_H_WAIT_2(x) ((x) & 0xff) + +#define VCR_V_WIDTH(x) (((x) & 0x3f) << 26) +#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8) +#define VCR_V_WAIT_2(x) ((x) & 0xff) + +#define RMCR_LCDC_EN_MX1 (1 << 1) + +#define RMCR_SELF_REF (1 << 0) + +#define LIER_EOF (1 << 1) + +struct imx_crtc { + struct drm_crtc base; + struct imx_drm_crtc *imx_drm_crtc; + int di_no; + int enabled; + void __iomem *regs; + u32 pwmr; + u32 lscr1; + u32 dmacr; + u32 pcr; + struct clk *clk; + struct device *dev; + int vblank_enable; + + struct drm_pending_vblank_event *page_flip_event; + struct drm_framebuffer *newfb; +}; + +#define to_imx_crtc(x) container_of(x, struct imx_crtc, base) + +static void imx_crtc_load_lut(struct drm_crtc *crtc) +{ +} + +#define PCR_BPIX_8 (3 << 25) +#define PCR_BPIX_12 (4 << 25) +#define PCR_BPIX_16 (5 << 25) +#define PCR_BPIX_18 (6 << 25) +#define PCR_END_SEL (1 << 18) +#define PCR_END_BYTE_SWAP (1 << 17) + +const char *fourcc_to_str(u32 fourcc) +{ + static char buf[5]; + + *(u32 *)buf = fourcc; + buf[4] = 0; + + return buf; +} + +static int imx_drm_crtc_set(struct drm_crtc *crtc, + struct drm_display_mode *mode) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + struct drm_framebuffer *fb = crtc->fb; + int lower_margin = mode->vsync_start - mode->vdisplay; + int upper_margin = mode->vtotal - mode->vsync_end; + int vsync_len = mode->vsync_end - mode->vsync_start; + int hsync_len = mode->hsync_end - mode->hsync_start; + int right_margin = mode->hsync_start - mode->hdisplay; + int left_margin = mode->htotal - mode->hsync_end; + unsigned long lcd_clk; + u32 pcr; + + lcd_clk = clk_get_rate(imx_crtc->clk) / 1000; + + if (!mode->clock) + return -EINVAL; + + pcr = DIV_ROUND_CLOSEST(lcd_clk, mode->clock); + if (--pcr > 0x3f) + pcr = 0x3f; + + switch (fb->pixel_format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + pcr |= PCR_BPIX_18; + pcr |= PCR_END_SEL | PCR_END_BYTE_SWAP; + break; + case DRM_FORMAT_RGB565: + if (cpu_is_mx1()) + pcr |= PCR_BPIX_12; + else + pcr |= PCR_BPIX_16; + break; + case DRM_FORMAT_RGB332: + pcr |= PCR_BPIX_8; + break; + default: + dev_err(imx_crtc->dev, "unsupported pixel format %s\n", + fourcc_to_str(fb->pixel_format)); + return -EINVAL; + } + + /* add sync polarities */ + pcr |= imx_crtc->pcr & ~(0x3f | (7 << 25)); + + dev_dbg(imx_crtc->dev, + "xres=%d hsync_len=%d left_margin=%d right_margin=%d\n", + mode->hdisplay, hsync_len, + left_margin, right_margin); + dev_dbg(imx_crtc->dev, + "yres=%d vsync_len=%d upper_margin=%d lower_margin=%d\n", + mode->vdisplay, vsync_len, + upper_margin, lower_margin); + + writel(VPW_VPW(mode->hdisplay * fb->bits_per_pixel / 8 / 4), + imx_crtc->regs + LCDC_VPW); + + writel(HCR_H_WIDTH(hsync_len - 1) | + HCR_H_WAIT_1(right_margin - 1) | + HCR_H_WAIT_2(left_margin - 3), + imx_crtc->regs + LCDC_HCR); + + writel(VCR_V_WIDTH(vsync_len) | + VCR_V_WAIT_1(lower_margin) | + VCR_V_WAIT_2(upper_margin), + imx_crtc->regs + LCDC_VCR); + + writel(SIZE_XMAX(mode->hdisplay) | SIZE_YMAX(mode->vdisplay), + imx_crtc->regs + LCDC_SIZE); + + writel(pcr, imx_crtc->regs + LCDC_PCR); + writel(imx_crtc->pwmr, imx_crtc->regs + LCDC_PWMR); + writel(imx_crtc->lscr1, imx_crtc->regs + LCDC_LSCR1); + /* reset default */ + writel(0x00040060, imx_crtc->regs + LCDC_DMACR); + + return 0; +} + +static int imx_drm_set_base(struct drm_crtc *crtc, int x, int y) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + struct imx_drm_buf_entry *entry; + struct drm_framebuffer *fb = crtc->fb; + unsigned long phys; + + entry = imx_drm_fb_get_buf(fb); + if (!entry) + return -EFAULT; + + phys = entry->paddr; + phys += x * (fb->bits_per_pixel >> 3); + phys += y * fb->pitches[0]; + + dev_dbg(imx_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys); + dev_dbg(imx_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y); + + writel(phys, imx_crtc->regs + LCDC_SSA); + + return 0; +} + +static int imx_crtc_mode_set(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, + int x, int y, + struct drm_framebuffer *old_fb) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + + imx_drm_set_base(crtc, x, y); + + dev_dbg(imx_crtc->dev, "mode->hdisplay: %d\n", mode->hdisplay); + dev_dbg(imx_crtc->dev, "mode->vdisplay: %d\n", mode->vdisplay); + + return imx_drm_crtc_set(crtc, mode); +} + +static void imx_crtc_enable(struct imx_crtc *imx_crtc) +{ + if (!imx_crtc->enabled) + clk_enable(imx_crtc->clk); + imx_crtc->enabled = 1; +} + +static void imx_crtc_disable(struct imx_crtc *imx_crtc) +{ + if (imx_crtc->enabled) + clk_disable(imx_crtc->clk); + imx_crtc->enabled = 0; +} + +static void imx_crtc_dpms(struct drm_crtc *crtc, int mode) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + + dev_dbg(imx_crtc->dev, "%s mode: %d\n", __func__, mode); + + switch (mode) { + case DRM_MODE_DPMS_ON: + imx_crtc_enable(imx_crtc); + break; + default: + imx_crtc_disable(imx_crtc); + break; + } +} + +static bool imx_crtc_mode_fixup(struct drm_crtc *crtc, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void imx_crtc_prepare(struct drm_crtc *crtc) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + + imx_crtc_disable(imx_crtc); +} + +static void imx_crtc_commit(struct drm_crtc *crtc) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + + imx_crtc_enable(imx_crtc); +} + +static struct drm_crtc_helper_funcs imx_helper_funcs = { + .dpms = imx_crtc_dpms, + .mode_fixup = imx_crtc_mode_fixup, + .mode_set = imx_crtc_mode_set, + .prepare = imx_crtc_prepare, + .commit = imx_crtc_commit, + .load_lut = imx_crtc_load_lut, +}; + +static void imx_drm_handle_pageflip(struct imx_crtc *imx_crtc) +{ + struct drm_pending_vblank_event *e; + struct timeval now; + unsigned long flags; + struct drm_device *drm = imx_crtc->base.dev; + + spin_lock_irqsave(&drm->event_lock, flags); + + e = imx_crtc->page_flip_event; + + if (!e) { + spin_unlock_irqrestore(&drm->event_lock, flags); + return; + } + + do_gettimeofday(&now); + e->event.sequence = 0; + e->event.tv_sec = now.tv_sec; + e->event.tv_usec = now.tv_usec; + imx_crtc->page_flip_event = NULL; + + list_add_tail(&e->base.link, &e->base.file_priv->event_list); + + wake_up_interruptible(&e->base.file_priv->event_wait); + + spin_unlock_irqrestore(&drm->event_lock, flags); +} + +static int imx_crtc_enable_vblank(struct drm_crtc *crtc) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + + writel(LIER_EOF, imx_crtc->regs + LCDC_LIER); + + return 0; +} + +static void imx_crtc_disable_vblank(struct drm_crtc *crtc) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + + writel(0, imx_crtc->regs + LCDC_LIER); +} + +static irqreturn_t imx_irq_handler(int irq, void *dev_id) +{ + struct imx_crtc *imx_crtc = dev_id; + struct drm_device *drm = imx_crtc->base.dev; + + /* Acknowledge interrupt */ + readl(imx_crtc->regs + LCDC_LISR); + + drm_handle_vblank(drm, 0); + + if (imx_crtc->newfb) { + imx_crtc->base.fb = imx_crtc->newfb; + imx_crtc->newfb = NULL; + imx_drm_set_base(&imx_crtc->base, 0, 0); + imx_drm_handle_pageflip(imx_crtc); + imx_drm_crtc_vblank_put(imx_crtc->imx_drm_crtc); + } + + return IRQ_HANDLED; +} + +static int imx_page_flip(struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); + + if (imx_crtc->newfb) + return -EBUSY; + + imx_crtc->newfb = fb; + imx_crtc->page_flip_event = event; + imx_drm_crtc_vblank_get(imx_crtc->imx_drm_crtc); + + return 0; +} + +static const struct drm_crtc_funcs imx_crtc_funcs = { + .page_flip = imx_page_flip, +}; + +static const struct imx_drm_crtc_helper_funcs imx_imx_drm_helper = { + .enable_vblank = imx_crtc_enable_vblank, + .disable_vblank = imx_crtc_disable_vblank, +}; + +#define DRIVER_NAME "imx-lcdc-crtc" + +/* + * the pcr bits to be allowed to set in platform data + */ +#define PDATA_PCR (PCR_PIXPOL | PCR_FLMPOL | PCR_LPPOL | \ + PCR_CLKPOL | PCR_OEPOL | PCR_TFT | PCR_COLOR | \ + PCR_PBSIZ_8 | PCR_ACD(0x7f) | PCR_ACD_SEL | \ + PCR_SCLK_SEL | PCR_SHARP) + +static int __devinit imx_crtc_probe(struct platform_device *pdev) +{ + struct imx_crtc *imx_crtc; + struct resource *res; + int ret, irq; + u32 pcr_value = 0xf00080c0; + u32 lscr1_value = 0x00120300; + u32 pwmr_value = 0x00a903ff; + + imx_crtc = devm_kzalloc(&pdev->dev, sizeof(*imx_crtc), GFP_KERNEL); + if (!imx_crtc) + return -ENOMEM; + + imx_crtc->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + res = devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), DRIVER_NAME); + if (!res) + return -EBUSY; + + imx_crtc->regs = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!imx_crtc->regs) { + dev_err(&pdev->dev, "Cannot map frame buffer registers\n"); + return -EBUSY; + } + + irq = platform_get_irq(pdev, 0); + ret = devm_request_irq(&pdev->dev, irq, imx_irq_handler, 0, "imx_drm", + imx_crtc); + if (ret < 0) { + dev_err(&pdev->dev, "irq request failed with %d\n", ret); + return ret; + } + + imx_crtc->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(imx_crtc->clk)) { + ret = PTR_ERR(imx_crtc->clk); + dev_err(&pdev->dev, "unable to get clock: %d\n", ret); + return ret; + } + + clk_prepare_enable(imx_crtc->clk); + imx_crtc->enabled = 1; + + platform_set_drvdata(pdev, imx_crtc); + + imx_crtc->pcr = pcr_value & PDATA_PCR; + + if (imx_crtc->pcr != pcr_value) + dev_err(&pdev->dev, "invalid bits set in pcr: 0x%08x\n", + pcr_value & ~PDATA_PCR); + + imx_crtc->lscr1 = lscr1_value; + imx_crtc->pwmr = pwmr_value; + + ret = imx_drm_add_crtc(&imx_crtc->base, + &imx_crtc->imx_drm_crtc, + &imx_crtc_funcs, &imx_helper_funcs, + &imx_imx_drm_helper, THIS_MODULE); + if (ret) + goto err_init; + + dev_info(&pdev->dev, "probed\n"); + + return 0; + +err_init: + clk_disable_unprepare(imx_crtc->clk); + clk_put(imx_crtc->clk); + + return ret; +} + +static int __devexit imx_crtc_remove(struct platform_device *pdev) +{ + struct imx_crtc *imx_crtc = platform_get_drvdata(pdev); + + imx_drm_remove_crtc(imx_crtc->imx_drm_crtc); + + writel(0, imx_crtc->regs + LCDC_LIER); + + clk_disable_unprepare(imx_crtc->clk); + clk_put(imx_crtc->clk); + + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static const struct of_device_id imx_lcdc_dt_ids[] = { + { .compatible = "fsl,imx1-lcdc", .data = NULL, }, + { .compatible = "fsl,imx21-lcdc", .data = NULL, }, + { /* sentinel */ } +}; + +static struct platform_driver imx_crtc_driver = { + .remove = __devexit_p(imx_crtc_remove), + .probe = imx_crtc_probe, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = imx_lcdc_dt_ids, + }, +}; + +static int __init imx_lcdc_init(void) +{ + return platform_driver_register(&imx_crtc_driver); +} + +static void __exit imx_lcdc_exit(void) +{ + platform_driver_unregister(&imx_crtc_driver); +} + +module_init(imx_lcdc_init); +module_exit(imx_lcdc_exit) + +MODULE_DESCRIPTION("Freescale i.MX framebuffer driver"); +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/imx/imx-parallel-display.c b/drivers/gpu/drm/imx/imx-parallel-display.c new file mode 100644 index 0000000..8c96113 --- /dev/null +++ b/drivers/gpu/drm/imx/imx-parallel-display.c @@ -0,0 +1,228 @@ +/* + * i.MX drm driver - parallel display implementation + * + * Copyright (C) 2012 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + */ + +#include <linux/module.h> +#include <drm/drmP.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_crtc_helper.h> + +#include "imx-drm.h" + +#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) +#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder) + +struct imx_parallel_display { + struct drm_connector connector; + struct imx_drm_connector *imx_drm_connector; + struct drm_encoder encoder; + struct imx_drm_encoder *imx_drm_encoder; + struct device *dev; + void *edid; + int edid_len; +}; + +static enum drm_connector_status imx_pd_connector_detect(struct drm_connector *connector, + bool force) +{ + return connector_status_connected; +} + +static void imx_pd_connector_destroy(struct drm_connector *connector) +{ + /* do not free here */ +} + +static int imx_pd_connector_get_modes(struct drm_connector *connector) +{ + struct imx_parallel_display *imxpd = con_to_imxpd(connector); + int ret; + + drm_mode_connector_update_edid_property(connector, imxpd->edid); + ret = drm_add_edid_modes(connector, imxpd->edid); + connector->display_info.raw_edid = NULL; + + return ret; +} + +static int imx_pd_connector_mode_valid(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + return 0; +} + +static struct drm_encoder *imx_pd_connector_best_encoder(struct drm_connector *connector) +{ + struct imx_parallel_display *imxpd = con_to_imxpd(connector); + + return &imxpd->encoder; +} + +static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) +{ +} + +static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + return true; +} + +static void imx_pd_encoder_prepare(struct drm_encoder *encoder) +{ +} + +static void imx_pd_encoder_commit(struct drm_encoder *encoder) +{ +} + +static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ +} + +static void imx_pd_encoder_disable(struct drm_encoder *encoder) +{ +} + +static void imx_pd_encoder_destroy(struct drm_encoder *encoder) +{ + /* do not free here */ +} + +struct drm_connector_funcs imx_pd_connector_funcs = { + .dpms = drm_helper_connector_dpms, + .fill_modes = drm_helper_probe_single_connector_modes, + .detect = imx_pd_connector_detect, + .destroy = imx_pd_connector_destroy, +}; + +struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = { + .get_modes = imx_pd_connector_get_modes, + .best_encoder = imx_pd_connector_best_encoder, + .mode_valid = imx_pd_connector_mode_valid, +}; + +static struct drm_encoder_funcs imx_pd_encoder_funcs = { + .destroy = imx_pd_encoder_destroy, +}; + +static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { + .dpms = imx_pd_encoder_dpms, + .mode_fixup = imx_pd_encoder_mode_fixup, + .prepare = imx_pd_encoder_prepare, + .commit = imx_pd_encoder_commit, + .mode_set = imx_pd_encoder_mode_set, + .disable = imx_pd_encoder_disable, +}; + +static int imx_pd_register(struct imx_parallel_display *imxpd) +{ + int ret; + + drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder); + + imxpd->connector.funcs = &imx_pd_connector_funcs; + imxpd->encoder.funcs = &imx_pd_encoder_funcs; + + drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs); + ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder, THIS_MODULE); + if (ret) { + dev_err(imxpd->dev, "adding encoder failed with %d\n", ret); + return ret; + } + + drm_connector_helper_add(&imxpd->connector, &imx_pd_connector_helper_funcs); + + ret = imx_drm_add_connector(&imxpd->connector, &imxpd->imx_drm_connector, + THIS_MODULE); + if (ret) { + imx_drm_remove_encoder(imxpd->imx_drm_encoder); + dev_err(imxpd->dev, "adding connector failed with %d\n", ret); + return ret; + } + + imxpd->connector.encoder = &imxpd->encoder; + + return 0; +} + +static int __devinit imx_pd_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const u8 *edidp; + struct imx_parallel_display *imxpd; + int ret; + + imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL); + if (!imxpd) + return -ENOMEM; + + edidp = of_get_property(np, "edid", &imxpd->edid_len); + + imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL); + imxpd->encoder.possible_crtcs = 0x1; + imxpd->encoder.possible_clones = 0x1; + imxpd->dev = &pdev->dev; + + ret = imx_pd_register(imxpd); + if (ret) + return ret; + + platform_set_drvdata(pdev, imxpd); + + return 0; +} + +static int __devexit imx_pd_remove(struct platform_device *pdev) +{ + struct imx_parallel_display *imxpd = platform_get_drvdata(pdev); + struct drm_connector *connector = &imxpd->connector; + struct drm_encoder *encoder = &imxpd->encoder; + + drm_mode_connector_detach_encoder(connector, encoder); + + imx_drm_remove_connector(imxpd->imx_drm_connector); + imx_drm_remove_encoder(imxpd->imx_drm_encoder); + + return 0; +} + +static const struct of_device_id imx_pd_dt_ids[] = { + { .compatible = "fsl,imx-parallel-display", .data = NULL, }, + { /* sentinel */ } +}; + +static struct platform_driver imx_pd_driver = { + .probe = imx_pd_probe, + .remove = __devexit_p(imx_pd_remove), + .driver = { + .of_match_table = imx_pd_dt_ids, + .name = "imx-parallel-display", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(imx_pd_driver); + +MODULE_DESCRIPTION("i.MX parallel display driver"); +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); +MODULE_LICENSE("GPL"); -- 1.7.10 ^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [PATCH 1/2] DRM: add Freescale i.MX LCDC driver 2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer @ 2012-05-22 21:28 ` Rob Clark 2012-05-23 7:47 ` Sascha Hauer 0 siblings, 1 reply; 42+ messages in thread From: Rob Clark @ 2012-05-22 21:28 UTC (permalink / raw) To: Sascha Hauer; +Cc: linux-arm-kernel, dri-devel just a few comments from a cursory review.. I need a bit more time for a more in-depth review but that won't be tonight so I thought I'd send what I have so far.. On Fri, May 18, 2012 at 6:27 AM, Sascha Hauer <s.hauer@pengutronix.de> wrote: > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > drivers/gpu/drm/Kconfig | 2 + > drivers/gpu/drm/Makefile | 1 + > drivers/gpu/drm/imx/Kconfig | 18 + > drivers/gpu/drm/imx/Makefile | 8 + > drivers/gpu/drm/imx/imx-drm-core.c | 745 ++++++++++++++++++++++++++++ > drivers/gpu/drm/imx/imx-fb.c | 179 +++++++ > drivers/gpu/drm/imx/imx-fbdev.c | 275 ++++++++++ > drivers/gpu/drm/imx/imx-gem.c | 343 +++++++++++++ > drivers/gpu/drm/imx/imx-lcdc-crtc.c | 517 +++++++++++++++++++ > drivers/gpu/drm/imx/imx-parallel-display.c | 228 +++++++++ > 10 files changed, 2316 insertions(+) > create mode 100644 drivers/gpu/drm/imx/Kconfig > create mode 100644 drivers/gpu/drm/imx/Makefile > create mode 100644 drivers/gpu/drm/imx/imx-drm-core.c > create mode 100644 drivers/gpu/drm/imx/imx-fb.c > create mode 100644 drivers/gpu/drm/imx/imx-fbdev.c > create mode 100644 drivers/gpu/drm/imx/imx-gem.c > create mode 100644 drivers/gpu/drm/imx/imx-lcdc-crtc.c > create mode 100644 drivers/gpu/drm/imx/imx-parallel-display.c > > diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig > index e354bc0..759502c 100644 > --- a/drivers/gpu/drm/Kconfig > +++ b/drivers/gpu/drm/Kconfig > @@ -186,3 +186,5 @@ source "drivers/gpu/drm/vmwgfx/Kconfig" > source "drivers/gpu/drm/gma500/Kconfig" > > source "drivers/gpu/drm/udl/Kconfig" > + > +source "drivers/gpu/drm/imx/Kconfig" > diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile > index c20da5b..6569d8d 100644 > --- a/drivers/gpu/drm/Makefile > +++ b/drivers/gpu/drm/Makefile > @@ -42,4 +42,5 @@ obj-$(CONFIG_DRM_NOUVEAU) +=nouveau/ > obj-$(CONFIG_DRM_EXYNOS) +=exynos/ > obj-$(CONFIG_DRM_GMA500) += gma500/ > obj-$(CONFIG_DRM_UDL) += udl/ > +obj-$(CONFIG_DRM_IMX) += imx/ > obj-y += i2c/ > diff --git a/drivers/gpu/drm/imx/Kconfig b/drivers/gpu/drm/imx/Kconfig > new file mode 100644 > index 0000000..5fc3a44 > --- /dev/null > +++ b/drivers/gpu/drm/imx/Kconfig > @@ -0,0 +1,18 @@ > +config DRM_IMX > + tristate "DRM Support for Freescale i.MX" > + select DRM_KMS_HELPER > + depends on DRM && ARCH_MXC > + > +config DRM_IMX_FB_HELPER > + tristate "provide legacy framebuffer /dev/fb0" > + depends on DRM_IMX > + > +config DRM_IMX_LCDC > + tristate "DRM Support for Freescale i.MX1 and i.MX2" > + depends on DRM_IMX > + help > + Choose this if you have a i.MX1, i.MX21, i.MX25 or i.MX27 processor. do you have something like cpu_is_imx2() type macros? It would be preferable not to have a compile time config option for building for certain hw versions. Ie. on OMAP we could do something like 'if (cpu_is_omap3xxx()) { ... }' if there was something that needed to be done different on omap3 family of devices. This way you could choose to build a kernel supporting either a single omap variants, or all omap variants. > + > +config DRM_IMX_PARALLEL_DISPLAY > + tristate "Support for parallel displays" > + depends on DRM_IMX > diff --git a/drivers/gpu/drm/imx/Makefile b/drivers/gpu/drm/imx/Makefile > new file mode 100644 > index 0000000..0f7c038 > --- /dev/null > +++ b/drivers/gpu/drm/imx/Makefile > @@ -0,0 +1,8 @@ > + > +imxdrm-objs := imx-drm-core.o imx-fb.o imx-gem.o > + > +obj-$(CONFIG_DRM_IMX) += imxdrm.o > + > +obj-$(CONFIG_DRM_IMX_PARALLEL_DISPLAY) += imx-parallel-display.o > +obj-$(CONFIG_DRM_IMX_LCDC) += imx-lcdc-crtc.o > +obj-$(CONFIG_DRM_IMX_FB_HELPER) += imx-fbdev.o > diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c > new file mode 100644 > index 0000000..29f5f10 > --- /dev/null > +++ b/drivers/gpu/drm/imx/imx-drm-core.c > @@ -0,0 +1,745 @@ > +/* > + * simple drm driver > + * > + * Copyright (C) 2011 Sascha Hauer, Pengutronix > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > + > +#include <linux/device.h> > +#include <linux/platform_device.h> > +#include <drm/drmP.h> > +#include <drm/drm_fb_helper.h> > +#include <drm/drm_crtc_helper.h> > +#include <linux/fb.h> > +#include <asm/fb.h> > +#include <linux/module.h> > + > +#include "imx-drm.h" > + > +#define MAX_CRTC 4 > + > +struct imx_drm_device { > + struct drm_device *drm; > + struct device *dev; > + struct list_head crtc_list; > + struct list_head encoder_list; > + struct list_head connector_list; > + struct mutex mutex; > + int references; > +}; > + > +struct imx_drm_crtc { > + struct drm_crtc *crtc; > + struct list_head list; > + struct imx_drm_device *imxdrm; > + int pipe; > + struct drm_crtc_helper_funcs crtc_helper_funcs; > + struct drm_crtc_funcs crtc_funcs; > + struct imx_drm_crtc_helper_funcs imx_drm_helper_funcs; > + struct module *owner; > +}; > + > +struct imx_drm_encoder { > + struct drm_encoder *encoder; > + struct list_head list; > + struct module *owner; > +}; > + > +struct imx_drm_connector { > + struct drm_connector *connector; > + struct list_head list; > + struct module *owner; > +}; > + > +static int imx_drm_driver_firstopen(struct drm_device *drm) > +{ > + if (!imx_drm_device_get()) > + return -EINVAL; > + > + return 0; > +} > + > +static void imx_drm_driver_lastclose(struct drm_device *drm) > +{ > + imx_drm_device_put(); > +} > + > +static int imx_drm_driver_unload(struct drm_device *drm) > +{ > + struct imx_drm_device *imxdrm = drm->dev_private; > + > + drm_mode_config_cleanup(imxdrm->drm); > + drm_kms_helper_poll_fini(imxdrm->drm); > + > + return 0; > +} > + > +/* > + * We don't care at all for crtc numbers, but the core expects the > + * crtcs to be numbered > + */ > +static struct imx_drm_crtc *imx_drm_crtc_by_num(struct imx_drm_device *imxdrm, > + int num) > +{ > + struct imx_drm_crtc *imx_drm_crtc; > + > + list_for_each_entry(imx_drm_crtc, &imxdrm->crtc_list, list) > + if (imx_drm_crtc->pipe == num) > + return imx_drm_crtc; > + return NULL; > +} > + > +int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc) > +{ > + return drm_vblank_get(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); > +} > +EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_get); > + > +void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc) > +{ > + drm_vblank_put(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); > +} > +EXPORT_SYMBOL_GPL(imx_drm_crtc_vblank_put); > + > +void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc) > +{ > + drm_handle_vblank(imx_drm_crtc->imxdrm->drm, imx_drm_crtc->pipe); > +} > +EXPORT_SYMBOL_GPL(imx_drm_handle_vblank); > + > +static int imx_drm_enable_vblank(struct drm_device *drm, int crtc) > +{ > + struct imx_drm_device *imxdrm = drm->dev_private; > + struct imx_drm_crtc *imx_drm_crtc; > + int ret; > + > + imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc); > + if (!imx_drm_crtc) > + return -EINVAL; > + > + if (!imx_drm_crtc->imx_drm_helper_funcs.enable_vblank) > + return -ENOSYS; > + > + ret = imx_drm_crtc->imx_drm_helper_funcs.enable_vblank(imx_drm_crtc->crtc); > + return ret; > +} > + > +static void imx_drm_disable_vblank(struct drm_device *drm, int crtc) > +{ > + struct imx_drm_device *imxdrm = drm->dev_private; > + struct imx_drm_crtc *imx_drm_crtc; > + > + imx_drm_crtc = imx_drm_crtc_by_num(imxdrm, crtc); > + if (!imx_drm_crtc) > + return; > + > + if (!imx_drm_crtc->imx_drm_helper_funcs.disable_vblank) > + return; > + > + imx_drm_crtc->imx_drm_helper_funcs.disable_vblank(imx_drm_crtc->crtc); > +} > + > +static struct vm_operations_struct imx_drm_gem_vm_ops = { > + .fault = imx_drm_gem_fault, > + .open = drm_gem_vm_open, > + .close = drm_gem_vm_close, > +}; > + > +static const struct file_operations imx_drm_driver_fops = { > + .owner = THIS_MODULE, > + .open = drm_open, > + .release = drm_release, > + .unlocked_ioctl = drm_ioctl, > + .mmap = imx_drm_gem_mmap, > + .poll = drm_poll, > + .fasync = drm_fasync, > + .read = drm_read, > + .llseek = noop_llseek, > +}; > + > +static struct imx_drm_device *imx_drm_device; > + > +static struct imx_drm_device *__imx_drm_device(void) > +{ > + return imx_drm_device; > +} > + > +struct drm_device *imx_drm_device_get(void) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + struct imx_drm_encoder *enc; > + struct imx_drm_connector *con; > + struct imx_drm_crtc *crtc; > + > + mutex_lock(&imxdrm->mutex); > + > + list_for_each_entry(enc, &imxdrm->encoder_list, list) { > + if (!try_module_get(enc->owner)) { > + dev_err(imxdrm->dev, "could not get module %s\n", > + module_name(enc->owner)); > + goto unwind_enc; > + } > + } > + > + list_for_each_entry(con, &imxdrm->connector_list, list) { > + if (!try_module_get(con->owner)) { > + dev_err(imxdrm->dev, "could not get module %s\n", > + module_name(con->owner)); > + goto unwind_con; > + } > + } > + > + list_for_each_entry(crtc, &imxdrm->crtc_list, list) { > + if (!try_module_get(crtc->owner)) { > + dev_err(imxdrm->dev, "could not get module %s\n", > + module_name(crtc->owner)); > + goto unwind_crtc; > + } > + } > + > + imxdrm->references++; > + > + mutex_unlock(&imxdrm->mutex); > + > + return imx_drm_device->drm; > + > +unwind_crtc: > + list_for_each_entry_continue_reverse(crtc, &imxdrm->crtc_list, list) > + module_put(crtc->owner); > +unwind_con: > + list_for_each_entry_continue_reverse(con, &imxdrm->connector_list, list) > + module_put(con->owner); > +unwind_enc: > + list_for_each_entry_continue_reverse(enc, &imxdrm->encoder_list, list) > + module_put(enc->owner); > + > + mutex_unlock(&imxdrm->mutex); > + > + return NULL; > + > +} > +EXPORT_SYMBOL_GPL(imx_drm_device_get); > + > +void imx_drm_device_put(void) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + struct imx_drm_encoder *enc; > + struct imx_drm_connector *con; > + struct imx_drm_crtc *crtc; > + > + mutex_lock(&imxdrm->mutex); > + > + list_for_each_entry(crtc, &imxdrm->crtc_list, list) > + module_put(crtc->owner); > + > + list_for_each_entry(con, &imxdrm->connector_list, list) > + module_put(con->owner); > + > + list_for_each_entry(enc, &imxdrm->encoder_list, list) > + module_put(enc->owner); > + > + imxdrm->references--; > + > + mutex_unlock(&imxdrm->mutex); > +} > +EXPORT_SYMBOL_GPL(imx_drm_device_put); > + > +static int drm_mode_group_reinit(struct drm_device *dev) > +{ > + struct drm_mode_group *group = &dev->primary->mode_group; > + uint32_t *id_list = group->id_list; > + int ret; > + > + ret = drm_mode_group_init_legacy_group(dev, group); > + if (ret < 0) > + return ret; > + > + kfree(id_list); > + return 0; > +} > + > +/* > + * register an encoder to the drm core > + */ > +static int imx_drm_encoder_register(struct imx_drm_encoder *imx_drm_encoder) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + > + drm_encoder_init(imxdrm->drm, imx_drm_encoder->encoder, > + imx_drm_encoder->encoder->funcs, > + DRM_MODE_ENCODER_TMDS); > + > + drm_mode_group_reinit(imxdrm->drm); > + > + return 0; > +} > + > +/* > + * unregister an encoder from the drm core > + */ > +static void imx_drm_encoder_unregister(struct imx_drm_encoder *imx_drm_encoder) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + > + drm_encoder_cleanup(imx_drm_encoder->encoder); > + > + drm_mode_group_reinit(imxdrm->drm); > +} > + > +/* > + * register a connector to the drm core > + */ > +static int imx_drm_connector_register(struct imx_drm_connector *imx_drm_connector) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + int ret; > + > + drm_connector_init(imxdrm->drm, imx_drm_connector->connector, > + imx_drm_connector->connector->funcs, > + DRM_MODE_CONNECTOR_VGA); > + drm_mode_group_reinit(imxdrm->drm); > + ret = drm_sysfs_connector_add(imx_drm_connector->connector); > + if (ret) > + goto err; > + > + return 0; > +err: > + > + return ret; > +} > + > +/* > + * unregister a connector from the drm core > + */ > +static void imx_drm_connector_unregister(struct imx_drm_connector *imx_drm_connector) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + > + drm_sysfs_connector_remove(imx_drm_connector->connector); > + drm_connector_cleanup(imx_drm_connector->connector); > + > + drm_mode_group_reinit(imxdrm->drm); > +} > + > +/* > + * register a crtc to the drm core > + */ > +static int imx_drm_crtc_register(struct imx_drm_crtc *imx_drm_crtc) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + int ret; > + > + drm_crtc_init(imxdrm->drm, imx_drm_crtc->crtc, &imx_drm_crtc->crtc_funcs); > + ret = drm_mode_crtc_set_gamma_size(imx_drm_crtc->crtc, 256); > + if (ret) > + return ret; > + > + drm_crtc_helper_add(imx_drm_crtc->crtc, &imx_drm_crtc->crtc_helper_funcs); > + > + return 0; > +} > + > +/* > + * Called by the CRTC driver when all CRTCs are registered. This > + * puts all the pieces together and initializes the driver. > + * Once this is called no more CRTCs can be registered since > + * the drm core has hardcoded the number of crtcs in several > + * places. > + */ > +static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + int ret; > + > + imxdrm->drm = drm; > + > + drm->dev_private = imxdrm; > + > + /* > + * enable drm irq mode. > + * - with irq_enabled = 1, we can use the vblank feature. > + * > + * P.S. note that we wouldn't use drm irq handler but > + * just specific driver own one instead because > + * drm framework supports only one irq handler and > + * drivers can well take care of their interrupts > + */ > + drm->irq_enabled = 1; > + > + drm_mode_config_init(drm); > + imx_drm_mode_config_init(drm); > + > + mutex_lock(&imxdrm->mutex); > + > + drm_kms_helper_poll_init(imxdrm->drm); > + > + /* setup the grouping for the legacy output */ > + ret = drm_mode_group_init_legacy_group(imxdrm->drm, > + &imxdrm->drm->primary->mode_group); > + if (ret) > + goto err_init; > + > + ret = drm_vblank_init(imxdrm->drm, MAX_CRTC); > + if (ret) > + goto err_init; > + > + /* > + * with vblank_disable_allowed = 1, vblank interrupt will be disabled > + * by drm timer once a current process gives up ownership of > + * vblank event.(after drm_vblank_put function is called) > + */ > + imxdrm->drm->vblank_disable_allowed = 1; > + > + ret = 0; > + > +err_init: > + mutex_unlock(&imxdrm->mutex); > + > + return ret; > +} > + > +/* > + * imx_drm_add_crtc - add a new crtc > + * > + * The return value if !NULL is a cookie for the caller to pass to > + * imx_drm_remove_crtc later. > + */ > +int imx_drm_add_crtc(struct drm_crtc *crtc, > + struct imx_drm_crtc **new_crtc, > + const struct drm_crtc_funcs *crtc_funcs, > + const struct drm_crtc_helper_funcs *crtc_helper_funcs, > + const struct imx_drm_crtc_helper_funcs *imx_drm_helper_funcs, > + struct module *owner) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + struct imx_drm_crtc *imx_drm_crtc; > + int ret; > + > + mutex_lock(&imxdrm->mutex); > + > + if (imxdrm->references) { > + ret = -EBUSY; > + goto err_busy; > + } > + > + imx_drm_crtc = kzalloc(sizeof(*imx_drm_crtc), GFP_KERNEL); > + if (!imx_drm_crtc) { > + ret = -ENOMEM; > + goto err_alloc; > + } > + > + imx_drm_crtc->crtc_funcs = *crtc_funcs; > + imx_drm_crtc->crtc_helper_funcs = *crtc_helper_funcs; > + imx_drm_crtc->imx_drm_helper_funcs = *imx_drm_helper_funcs; > + > + WARN_ON(crtc_funcs->set_config); > + WARN_ON(crtc_funcs->destroy); > + > + imx_drm_crtc->crtc_funcs.set_config = drm_crtc_helper_set_config; > + imx_drm_crtc->crtc_funcs.destroy = drm_crtc_cleanup; > + > + imx_drm_crtc->crtc = crtc; > + imx_drm_crtc->imxdrm = imxdrm; > + > + imx_drm_crtc->owner = owner; > + > + list_add_tail(&imx_drm_crtc->list, &imxdrm->crtc_list); > + > + *new_crtc = imx_drm_crtc; > + > + ret = imx_drm_crtc_register(imx_drm_crtc); > + if (ret) > + goto err_register; > + > + mutex_unlock(&imxdrm->mutex); > + > + return 0; > + > +err_register: > + kfree(imx_drm_crtc); > +err_alloc: > +err_busy: > + mutex_unlock(&imxdrm->mutex); > + return ret; > +} > +EXPORT_SYMBOL_GPL(imx_drm_add_crtc); > + > +/* > + * imx_drm_remove_crtc - remove a crtc > + */ > +int imx_drm_remove_crtc(struct imx_drm_crtc *imx_drm_crtc) > +{ > + struct imx_drm_device *imxdrm = imx_drm_crtc->imxdrm; > + > + mutex_lock(&imxdrm->mutex); > + > + drm_crtc_cleanup(imx_drm_crtc->crtc); > + > + list_del(&imx_drm_crtc->list); > + > + mutex_unlock(&imxdrm->mutex); > + > + kfree(imx_drm_crtc); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(imx_drm_remove_crtc); > + > +/* > + * imx_drm_add_encoder - add a new encoder > + */ > +int imx_drm_add_encoder(struct drm_encoder *encoder, > + struct imx_drm_encoder **newenc, struct module *owner) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + struct imx_drm_encoder *imx_drm_encoder; > + int ret; > + > + mutex_lock(&imxdrm->mutex); > + > + if (imxdrm->references) { > + ret = -EBUSY; > + goto err_busy; > + } > + > + imx_drm_encoder = kzalloc(sizeof(struct imx_drm_encoder), GFP_KERNEL); > + if (!imx_drm_encoder) { > + ret = -ENOMEM; > + goto err_alloc; > + } > + > + imx_drm_encoder->encoder = encoder; > + imx_drm_encoder->owner = owner; > + > + ret = imx_drm_encoder_register(imx_drm_encoder); > + if (ret) { > + kfree(imx_drm_encoder); > + ret = -ENOMEM; > + goto err_register; > + } > + > + list_add_tail(&imx_drm_encoder->list, &imxdrm->encoder_list); > + > + *newenc = imx_drm_encoder; > + > + mutex_unlock(&imxdrm->mutex); > + > + return 0; > + > +err_register: > + kfree(imx_drm_encoder); > +err_alloc: > +err_busy: > + mutex_unlock(&imxdrm->mutex); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(imx_drm_add_encoder); > + > +/* > + * imx_drm_remove_encoder - remove an encoder > + */ > +int imx_drm_remove_encoder(struct imx_drm_encoder *imx_drm_encoder) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + > + mutex_lock(&imxdrm->mutex); > + > + imx_drm_encoder_unregister(imx_drm_encoder); > + > + list_del(&imx_drm_encoder->list); > + > + mutex_unlock(&imxdrm->mutex); > + > + kfree(imx_drm_encoder); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(imx_drm_remove_encoder); > + > +/* > + * imx_drm_add_connector - add a connector > + */ > +int imx_drm_add_connector(struct drm_connector *connector, > + struct imx_drm_connector **new_con, > + struct module *owner) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + struct imx_drm_connector *imx_drm_connector; > + int ret; > + > + mutex_lock(&imxdrm->mutex); > + > + if (imxdrm->references) { > + ret = -EBUSY; > + goto err_busy; > + } > + > + imx_drm_connector = kzalloc(sizeof(struct imx_drm_connector), GFP_KERNEL); > + if (!imx_drm_connector) { > + ret = -ENOMEM; > + goto err_alloc; > + } > + > + imx_drm_connector->connector = connector; > + imx_drm_connector->owner = owner; > + > + ret = imx_drm_connector_register(imx_drm_connector); > + if (ret) > + goto err_register; > + > + list_add_tail(&imx_drm_connector->list, &imxdrm->connector_list); > + > + *new_con = imx_drm_connector; > + > + mutex_unlock(&imxdrm->mutex); > + > + return 0; > + > +err_register: > + kfree(imx_drm_connector); > +err_alloc: > +err_busy: > + mutex_unlock(&imxdrm->mutex); > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(imx_drm_add_connector); > + > +/* > + * imx_drm_remove_connector - remove a connector > + */ > +int imx_drm_remove_connector(struct imx_drm_connector *imx_drm_connector) > +{ > + struct imx_drm_device *imxdrm = __imx_drm_device(); > + > + mutex_lock(&imxdrm->mutex); > + > + imx_drm_connector_unregister(imx_drm_connector); > + > + list_del(&imx_drm_connector->list); > + > + mutex_unlock(&imxdrm->mutex); > + > + kfree(imx_drm_connector); > + > + return 0; > +} > +EXPORT_SYMBOL_GPL(imx_drm_remove_connector); > + > +static struct drm_ioctl_desc imx_drm_ioctls[] = { > + /* none so far */ > +}; > + > +static struct drm_driver imx_drm_driver = { > + .driver_features = DRIVER_MODESET | DRIVER_GEM, > + .load = imx_drm_driver_load, > + .unload = imx_drm_driver_unload, > + .firstopen = imx_drm_driver_firstopen, > + .lastclose = imx_drm_driver_lastclose, > + .gem_free_object = imx_drm_gem_free_object, > + .gem_vm_ops = &imx_drm_gem_vm_ops, > + .dumb_create = imx_drm_gem_dumb_create, > + .dumb_map_offset = imx_drm_gem_dumb_map_offset, > + .dumb_destroy = imx_drm_gem_dumb_destroy, > + > + .get_vblank_counter = drm_vblank_count, > + .enable_vblank = imx_drm_enable_vblank, > + .disable_vblank = imx_drm_disable_vblank, > + .reclaim_buffers = drm_core_reclaim_buffers, > + .ioctls = imx_drm_ioctls, > + .num_ioctls = ARRAY_SIZE(imx_drm_ioctls), > + .fops = &imx_drm_driver_fops, > + .name = "imx-drm", > + .desc = "i.MX DRM graphics", > + .date = "20120507", > + .major = 1, > + .minor = 0, > + .patchlevel = 0, > +}; > + > +static int imx_drm_platform_probe(struct platform_device *pdev) > +{ > + imx_drm_device->dev = &pdev->dev; > + > + return drm_platform_init(&imx_drm_driver, pdev); > +} > + > +static int imx_drm_platform_remove(struct platform_device *pdev) > +{ > + drm_platform_exit(&imx_drm_driver, pdev); > + > + return 0; > +} > + > +static struct platform_driver imx_drm_pdrv = { > + .probe = imx_drm_platform_probe, > + .remove = __devexit_p(imx_drm_platform_remove), > + .driver = { > + .owner = THIS_MODULE, > + .name = "imx-drm", > + }, > +}; > + > +static struct platform_device *imx_drm_pdev; > + > +static int __init imx_drm_init(void) > +{ > + int ret; > + > + imx_drm_device = kzalloc(sizeof(*imx_drm_device), GFP_KERNEL); > + if (!imx_drm_device) > + return -ENOMEM; > + > + mutex_init(&imx_drm_device->mutex); > + INIT_LIST_HEAD(&imx_drm_device->crtc_list); > + INIT_LIST_HEAD(&imx_drm_device->connector_list); > + INIT_LIST_HEAD(&imx_drm_device->encoder_list); > + > + imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0); > + if (!imx_drm_pdev) { > + ret = -EINVAL; > + goto err_pdev; > + } > + > + imx_drm_pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32), > + > + ret = platform_driver_register(&imx_drm_pdrv); > + if (ret) > + goto err_pdrv; > + > + return 0; > + > +err_pdev: > + kfree(imx_drm_device); > +err_pdrv: > + platform_device_unregister(imx_drm_pdev); > + > + return ret; > +} > + > +static void __exit imx_drm_exit(void) > +{ > + DRM_DEBUG_DRIVER("%s\n", __FILE__); > + > + platform_device_unregister(imx_drm_pdev); > + platform_driver_unregister(&imx_drm_pdrv); > + > + kfree(imx_drm_device); > +} > + > +module_init(imx_drm_init); > +module_exit(imx_drm_exit); > + > +MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); > +MODULE_DESCRIPTION("i.MX drm driver core"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/gpu/drm/imx/imx-fb.c b/drivers/gpu/drm/imx/imx-fb.c > new file mode 100644 > index 0000000..5a08c86 > --- /dev/null > +++ b/drivers/gpu/drm/imx/imx-fb.c > @@ -0,0 +1,179 @@ > +/* > + * i.MX drm driver > + * > + * Copyright (C) 2012 Sascha Hauer, Pengutronix > + * > + * Based on Samsung Exynos code > + * > + * Copyright (c) 2011 Samsung Electronics Co., Ltd. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > +#include <linux/module.h> > +#include <drm/drmP.h> > +#include <drm/drm_crtc.h> > +#include <drm/drm_crtc_helper.h> > + > +#include "imx-drm.h" > + > +#define to_imx_drm_fb(x) container_of(x, struct imx_drm_fb, fb) > + > +/* > + * imx specific framebuffer structure. > + * > + * @fb: drm framebuffer obejct. > + * @imx_drm_gem_obj: drm ec specific gem object containing a gem object. > + * @entry: pointer to ec drm buffer entry object. > + * - containing only the information to physically continuous memory > + * region allocated at default framebuffer creation. > + */ > +struct imx_drm_fb { > + struct drm_framebuffer fb; > + struct imx_drm_gem_obj *imx_drm_gem_obj; > + struct imx_drm_buf_entry *entry; > +}; > + > +static void imx_drm_fb_destroy(struct drm_framebuffer *fb) > +{ > + struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb); > + > + drm_framebuffer_cleanup(fb); > + > + /* > + * default framebuffer has no gem object so > + * a buffer of the default framebuffer should be released at here. > + */ > + if (!imx_drm_fb->imx_drm_gem_obj && imx_drm_fb->entry) > + imx_drm_buf_destroy(fb->dev, imx_drm_fb->entry); > + > + kfree(imx_drm_fb); > +} > + > +static int imx_drm_fb_create_handle(struct drm_framebuffer *fb, > + struct drm_file *file_priv, unsigned int *handle) > +{ > + struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb); > + > + return drm_gem_handle_create(file_priv, > + &imx_drm_fb->imx_drm_gem_obj->base, handle); > +} > + > +static struct drm_framebuffer_funcs imx_drm_fb_funcs = { > + .destroy = imx_drm_fb_destroy, > + .create_handle = imx_drm_fb_create_handle, > +}; > + > +static struct drm_framebuffer *imx_drm_fb_create(struct drm_device *dev, > + struct drm_file *file_priv, struct drm_mode_fb_cmd2 *mode_cmd) > +{ > + struct imx_drm_fb *imx_drm_fb; > + struct drm_framebuffer *fb; > + struct drm_gem_object *obj; > + unsigned int size; > + int ret; > + u32 bpp, depth; > + > + drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); > + > + mode_cmd->pitches[0] = max(mode_cmd->pitches[0], > + mode_cmd->width * (bpp >> 3)); > + > + dev_dbg(dev->dev, "drm fb create(%dx%d)\n", > + mode_cmd->width, mode_cmd->height); > + > + imx_drm_fb = kzalloc(sizeof(*imx_drm_fb), GFP_KERNEL); > + if (!imx_drm_fb) { > + dev_err(dev->dev, "failed to allocate drm framebuffer.\n"); > + return ERR_PTR(-ENOMEM); > + } > + > + fb = &imx_drm_fb->fb; > + ret = drm_framebuffer_init(dev, fb, &imx_drm_fb_funcs); > + if (ret) { > + dev_err(dev->dev, "failed to initialize framebuffer.\n"); > + goto err_init; > + } > + > + dev_dbg(dev->dev, "create: fb id: %d\n", fb->base.id); > + > + size = mode_cmd->pitches[0] * mode_cmd->height; > + > + /* > + * without file_priv we are called from imx_drm_fbdev_create in which > + * case we only create a framebuffer without a handle. > + */ > + if (!file_priv) { > + struct imx_drm_buf_entry *entry; > + > + entry = imx_drm_buf_create(dev, size); > + if (IS_ERR(entry)) { > + ret = PTR_ERR(entry); > + goto err_buffer; > + } > + > + imx_drm_fb->entry = entry; > + } else { > + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); > + if (!obj) { > + ret = -EINVAL; > + goto err_buffer; > + } > + > + imx_drm_fb->imx_drm_gem_obj = to_imx_drm_gem_obj(obj); > + > + drm_gem_object_unreference_unlocked(obj); the fb probably should hold the reference to the GEM obj until it is deleted.. so you don't end up freeing the buffer you are scanning out until you are done scanning it out. Possibly this gets a bit more straightforward if you don't have to special case the default/fbcon framebuffer? IIRC, Laurent had sent a patch recently to fix the same issue in the exynos driver. > + imx_drm_fb->entry = imx_drm_fb->imx_drm_gem_obj->entry; > + } > + > + drm_helper_mode_fill_fb_struct(fb, mode_cmd); > + > + return fb; > + > +err_buffer: > + drm_framebuffer_cleanup(fb); > + > +err_init: > + kfree(imx_drm_fb); > + > + return ERR_PTR(ret); > +} > + > +struct imx_drm_buf_entry *imx_drm_fb_get_buf(struct drm_framebuffer *fb) > +{ > + struct imx_drm_fb *imx_drm_fb = to_imx_drm_fb(fb); > + struct imx_drm_buf_entry *entry; > + > + entry = imx_drm_fb->entry; > + > + return entry; > +} > +EXPORT_SYMBOL_GPL(imx_drm_fb_get_buf); > + > +static struct drm_mode_config_funcs imx_drm_mode_config_funcs = { > + .fb_create = imx_drm_fb_create, > +}; > + > +void imx_drm_mode_config_init(struct drm_device *dev) > +{ > + dev->mode_config.min_width = 64; > + dev->mode_config.min_height = 64; > + > + /* > + * set max width and height as default value(4096x4096). > + * this value would be used to check framebuffer size limitation > + * at drm_mode_addfb(). > + */ > + dev->mode_config.max_width = 4096; > + dev->mode_config.max_height = 4096; > + > + dev->mode_config.funcs = &imx_drm_mode_config_funcs; > +} > diff --git a/drivers/gpu/drm/imx/imx-fbdev.c b/drivers/gpu/drm/imx/imx-fbdev.c > new file mode 100644 > index 0000000..f038797 > --- /dev/null > +++ b/drivers/gpu/drm/imx/imx-fbdev.c > @@ -0,0 +1,275 @@ > +/* > + * i.MX drm driver > + * > + * Copyright (C) 2012 Sascha Hauer, Pengutronix > + * > + * Based on Samsung Exynos code > + * > + * Copyright (c) 2011 Samsung Electronics Co., Ltd. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > +#include <linux/module.h> > +#include <drm/drmP.h> > +#include <drm/drm_crtc.h> > +#include <drm/drm_fb_helper.h> > +#include <drm/drm_crtc_helper.h> > + > +#include "imx-drm.h" > + > +#define MAX_CONNECTOR 4 > +#define PREFERRED_BPP 16 > + > +static struct fb_ops imx_drm_fb_ops = { > + .owner = THIS_MODULE, > + .fb_fillrect = cfb_fillrect, > + .fb_copyarea = cfb_copyarea, > + .fb_imageblit = cfb_imageblit, > + .fb_check_var = drm_fb_helper_check_var, > + .fb_set_par = drm_fb_helper_set_par, > + .fb_blank = drm_fb_helper_blank, > + .fb_pan_display = drm_fb_helper_pan_display, > + .fb_setcmap = drm_fb_helper_setcmap, > +}; > + > +static int imx_drm_fbdev_update(struct drm_fb_helper *helper, > + struct drm_framebuffer *fb, > + unsigned int fb_width, > + unsigned int fb_height) > +{ > + struct fb_info *fbi = helper->fbdev; > + struct drm_device *drm = helper->dev; > + struct imx_drm_buf_entry *entry; > + unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3); > + unsigned long offset; > + > + drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); > + drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height); > + > + entry = imx_drm_fb_get_buf(fb); > + if (!entry) { > + dev_dbg(drm->dev, "entry is null.\n"); > + return -EFAULT; > + } > + > + offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3); > + offset += fbi->var.yoffset * fb->pitches[0]; > + > + drm->mode_config.fb_base = entry->paddr; > + fbi->screen_base = entry->vaddr + offset; > + fbi->fix.smem_start = entry->paddr + offset; > + fbi->screen_size = size; > + fbi->fix.smem_len = size; > + fbi->flags |= FBINFO_CAN_FORCE_OUTPUT; > + > + return 0; > +} > + > +static int imx_drm_fbdev_create(struct drm_fb_helper *helper, > + struct drm_fb_helper_surface_size *sizes) > +{ > + struct drm_device *drm = helper->dev; > + struct fb_info *fbi; > + struct drm_framebuffer *fb; > + struct drm_mode_fb_cmd2 mode_cmd = { 0 }; > + struct platform_device *pdev = drm->platformdev; > + int ret; > + > + dev_dbg(drm->dev, "surface width(%d), height(%d) and bpp(%d\n", > + sizes->surface_width, sizes->surface_height, > + sizes->surface_bpp); > + > + mode_cmd.width = sizes->surface_width; > + mode_cmd.height = sizes->surface_height; > + mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, > + sizes->surface_depth); > + > + mutex_lock(&drm->struct_mutex); > + > + fbi = framebuffer_alloc(0, &pdev->dev); > + if (!fbi) { > + ret = -ENOMEM; > + goto err_fb_alloc; > + } > + > + fb = drm->mode_config.funcs->fb_create(drm, NULL, &mode_cmd); > + if (IS_ERR(fb)) { > + dev_err(drm->dev, "failed to create drm framebuffer.\n"); > + ret = PTR_ERR(fb); > + goto err_fb_create; > + } > + > + helper->fb = fb; > + helper->fbdev = fbi; > + > + fbi->par = helper; > + fbi->flags = FBINFO_FLAG_DEFAULT; > + fbi->fbops = &imx_drm_fb_ops; > + > + ret = fb_alloc_cmap(&fbi->cmap, 256, 0); > + if (ret) > + goto err_alloc_cmap; > + > + ret = imx_drm_fbdev_update(helper, helper->fb, sizes->fb_width, > + sizes->fb_height); > + if (ret) > + goto err_fbdev_update; > + > + mutex_unlock(&drm->struct_mutex); > + > + return 0; > + > +err_fbdev_update: > + fb_dealloc_cmap(&fbi->cmap); > + > +err_alloc_cmap: > + fb->funcs->destroy(fb); > + > +err_fb_create: > + framebuffer_release(fbi); > + > +err_fb_alloc: > + mutex_unlock(&drm->struct_mutex); > + > + return ret; > +} > + > +static int imx_drm_fbdev_probe(struct drm_fb_helper *helper, > + struct drm_fb_helper_surface_size *sizes) > +{ > + int ret; > + > + BUG_ON(helper->fb); > + > + ret = imx_drm_fbdev_create(helper, sizes); > + if (ret) { > + dev_err(helper->dev->dev, "creating fbdev failed with %d\n", ret); > + return ret; > + } > + > + /* > + * fb_helper expects a value more than 1 if succeed > + * because register_framebuffer() should be called. > + */ > + return 1; > +} > + > +static struct drm_fb_helper_funcs imx_drm_fb_helper_funcs = { > + .fb_probe = imx_drm_fbdev_probe, > +}; > + > +static struct drm_fb_helper *imx_drm_fbdev_init(struct drm_device *drm, > + int preferred_bpp) > +{ > + struct drm_fb_helper *helper; > + unsigned int num_crtc; > + int ret; > + > + helper = kzalloc(sizeof(*helper), GFP_KERNEL); > + if (!helper) > + return NULL; > + > + helper->funcs = &imx_drm_fb_helper_funcs; > + > + num_crtc = drm->mode_config.num_crtc; > + > + ret = drm_fb_helper_init(drm, helper, num_crtc, MAX_CONNECTOR); > + if (ret) { > + dev_err(drm->dev, "initializing drm fb helper failed with %d\n", > + ret); > + goto err_init; > + } > + > + ret = drm_fb_helper_single_add_all_connectors(helper); > + if (ret) { > + dev_err(drm->dev, "registering drm_fb_helper_connector failed with %d\n", > + ret); > + goto err_setup; > + > + } > + > + ret = drm_fb_helper_initial_config(helper, preferred_bpp); > + if (ret) { > + dev_err(drm->dev, "initial config failed with %d\n", ret); > + goto err_setup; > + } > + > + return helper; > + > +err_setup: > + drm_fb_helper_fini(helper); > + > +err_init: > + kfree(helper); > + > + return NULL; > +} > + > +static void imx_drm_fbdev_fini(struct drm_fb_helper *helper) > +{ > + struct imx_drm_buf_entry *entry; > + > + if (helper->fbdev) { > + struct fb_info *info; > + int ret; > + > + info = helper->fbdev; > + ret = unregister_framebuffer(info); > + if (ret) > + dev_err(helper->dev->dev, "unregister_framebuffer failed with %d\n", > + ret); > + > + if (info->cmap.len) > + fb_dealloc_cmap(&info->cmap); > + > + entry = imx_drm_fb_get_buf(helper->fb); > + > + imx_drm_buf_destroy(helper->dev, entry); > + > + framebuffer_release(info); > + } > + > + drm_fb_helper_fini(helper); > + > + kfree(helper); > +} > + > +static struct drm_fb_helper *imx_fb_helper; > + > +static int __init imx_fb_helper_init(void) > +{ > + struct drm_device *drm = imx_drm_device_get(); > + int ret; > + > + if (!drm) > + return -EINVAL; > + > + imx_fb_helper = imx_drm_fbdev_init(drm, PREFERRED_BPP); > + if (!imx_fb_helper) { > + imx_drm_device_put(); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void __exit imx_fb_helper_exit(void) > +{ > + imx_drm_fbdev_fini(imx_fb_helper); > + imx_drm_device_put(); > +} > + > +late_initcall(imx_fb_helper_init); > +module_exit(imx_fb_helper_exit); > + > +MODULE_DESCRIPTION("Freescale i.MX legacy fb driver"); > +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/gpu/drm/imx/imx-gem.c b/drivers/gpu/drm/imx/imx-gem.c > new file mode 100644 > index 0000000..b0866fb > --- /dev/null > +++ b/drivers/gpu/drm/imx/imx-gem.c > @@ -0,0 +1,343 @@ > +/* > + * i.MX drm driver > + * > + * Copyright (C) 2012 Sascha Hauer, Pengutronix > + * > + * Based on Samsung Exynos code > + * > + * Copyright (c) 2011 Samsung Electronics Co., Ltd. > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > +#include <drm/drmP.h> > +#include <drm/drm.h> > +#include <drm/drm_crtc_helper.h> > + > +#include "imx-drm.h" > + > +static int lowlevel_buffer_allocate(struct drm_device *drm, > + struct imx_drm_buf_entry *entry) > +{ > + entry->vaddr = dma_alloc_writecombine(drm->dev, entry->size, > + (dma_addr_t *)&entry->paddr, GFP_KERNEL); > + if (!entry->vaddr) { > + dev_err(drm->dev, "failed to allocate buffer.\n"); > + return -ENOMEM; > + } > + > + dev_dbg(drm->dev, "allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n", > + (unsigned int)entry->vaddr, entry->paddr, entry->size); > + > + return 0; > +} > + > +static void lowlevel_buffer_free(struct drm_device *drm, > + struct imx_drm_buf_entry *entry) > +{ > + dma_free_writecombine(drm->dev, entry->size, entry->vaddr, > + entry->paddr); > +} > + > +struct imx_drm_buf_entry *imx_drm_buf_create(struct drm_device *drm, > + unsigned int size) > +{ > + struct imx_drm_buf_entry *entry; > + > + entry = kzalloc(sizeof(*entry), GFP_KERNEL); > + if (!entry) > + return ERR_PTR(-ENOMEM); > + > + entry->size = size; > + > + /* > + * allocate memory region with size and set the memory information > + * to vaddr and paddr of a entry object. > + */ > + if (lowlevel_buffer_allocate(drm, entry) < 0) { > + kfree(entry); > + return ERR_PTR(-ENOMEM); > + } > + > + return entry; > +} > + > +void imx_drm_buf_destroy(struct drm_device *drm, > + struct imx_drm_buf_entry *entry) > +{ > + lowlevel_buffer_free(drm, entry); > + > + kfree(entry); > + entry = NULL; > +} > +EXPORT_SYMBOL_GPL(imx_drm_buf_destroy); > + > +static unsigned int convert_to_vm_err_msg(int msg) > +{ > + unsigned int out_msg; > + > + switch (msg) { > + case 0: > + case -ERESTARTSYS: > + case -EINTR: > + out_msg = VM_FAULT_NOPAGE; > + break; > + > + case -ENOMEM: > + out_msg = VM_FAULT_OOM; > + break; > + > + default: > + out_msg = VM_FAULT_SIGBUS; > + break; > + } > + > + return out_msg; > +} > + > +static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj) > +{ > + return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT; > +} > + > +static struct imx_drm_gem_obj *imx_drm_gem_create(struct drm_device *drm, > + unsigned int size) > +{ > + struct imx_drm_gem_obj *imx_drm_gem_obj; > + struct imx_drm_buf_entry *entry; > + struct drm_gem_object *obj; > + int ret; > + > + size = roundup(size, PAGE_SIZE); > + > + imx_drm_gem_obj = kzalloc(sizeof(*imx_drm_gem_obj), GFP_KERNEL); > + if (!imx_drm_gem_obj) > + return ERR_PTR(-ENOMEM); > + > + /* allocate the new buffer object and memory region. */ > + entry = imx_drm_buf_create(drm, size); > + if (!entry) { > + ret = -ENOMEM; > + goto err_alloc; > + } > + > + imx_drm_gem_obj->entry = entry; > + > + obj = &imx_drm_gem_obj->base; > + > + ret = drm_gem_object_init(drm, obj, size); > + if (ret) { > + dev_err(drm->dev, "initializing GEM object failed with %d\n", ret); > + goto err_obj_init; > + } > + > + ret = drm_gem_create_mmap_offset(obj); > + if (ret) { > + dev_err(drm->dev, "creating mmap offset failed with %d\n", ret); > + goto err_create_mmap_offset; > + } > + > + return imx_drm_gem_obj; > + > +err_create_mmap_offset: > + drm_gem_object_release(obj); > + > +err_obj_init: > + imx_drm_buf_destroy(drm, imx_drm_gem_obj->entry); > + > +err_alloc: > + kfree(imx_drm_gem_obj); > + > + return ERR_PTR(ret); > +} > + > +static struct imx_drm_gem_obj *imx_drm_gem_create_with_handle(struct drm_file *file_priv, > + struct drm_device *drm, unsigned int size, > + unsigned int *handle) > +{ > + struct imx_drm_gem_obj *imx_drm_gem_obj; > + struct drm_gem_object *obj; > + int ret; > + > + imx_drm_gem_obj = imx_drm_gem_create(drm, size); > + if (IS_ERR(imx_drm_gem_obj)) > + return imx_drm_gem_obj; > + > + obj = &imx_drm_gem_obj->base; > + > + /* > + * allocate a id of idr table where the obj is registered > + * and handle has the id what user can see. > + */ > + ret = drm_gem_handle_create(file_priv, obj, handle); > + if (ret) > + goto err_handle_create; > + > + /* drop reference from allocate - handle holds it now. */ > + drm_gem_object_unreference_unlocked(obj); > + > + return imx_drm_gem_obj; > + > +err_handle_create: > + imx_drm_gem_free_object(obj); > + > + return ERR_PTR(ret); > +} > + > +static int imx_drm_gem_mmap_buffer(struct file *filp, > + struct vm_area_struct *vma) > +{ > + struct drm_gem_object *obj = filp->private_data; > + struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj); > + struct imx_drm_buf_entry *entry; > + unsigned long pfn, vm_size; > + > + vma->vm_flags |= VM_IO | VM_RESERVED; > + > + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); pgprot_writecombine()? > + vma->vm_file = filp; > + > + vm_size = vma->vm_end - vma->vm_start; > + /* > + * an entry contains information to physically continuous memory > + * allocated by user request or at framebuffer creation. > + */ > + entry = imx_drm_gem_obj->entry; > + > + /* check if user-requested size is valid. */ > + if (vm_size > entry->size) > + return -EINVAL; > + > + /* > + * get page frame number to physical memory to be mapped > + * to user space. > + */ > + pfn = imx_drm_gem_obj->entry->paddr >> PAGE_SHIFT; > + > + if (remap_pfn_range(vma, vma->vm_start, pfn, vm_size, > + vma->vm_page_prot)) { > + dev_err(obj->dev->dev, "failed to remap pfn range.\n"); > + return -EAGAIN; > + } > + > + return 0; > +} > + > +static const struct file_operations imx_drm_gem_fops = { > + .mmap = imx_drm_gem_mmap_buffer, > +}; > + > +int imx_drm_gem_init_object(struct drm_gem_object *obj) > +{ > + return 0; > +} > + > +void imx_drm_gem_free_object(struct drm_gem_object *gem_obj) > +{ > + struct imx_drm_gem_obj *imx_drm_gem_obj; > + > + if (gem_obj->map_list.map) > + drm_gem_free_mmap_offset(gem_obj); > + > + drm_gem_object_release(gem_obj); > + > + imx_drm_gem_obj = to_imx_drm_gem_obj(gem_obj); > + > + imx_drm_buf_destroy(gem_obj->dev, imx_drm_gem_obj->entry); > + > + kfree(imx_drm_gem_obj); > +} > + > +int imx_drm_gem_dumb_create(struct drm_file *file_priv, > + struct drm_device *dev, struct drm_mode_create_dumb *args) > +{ > + struct imx_drm_gem_obj *imx_drm_gem_obj; > + > + /* FIXME: This should be configured by the crtc driver */ > + args->pitch = args->width * args->bpp >> 3; > + args->size = args->pitch * args->height; > + > + imx_drm_gem_obj = imx_drm_gem_create_with_handle(file_priv, dev, args->size, > + &args->handle); > + if (IS_ERR(imx_drm_gem_obj)) > + return PTR_ERR(imx_drm_gem_obj); > + > + return 0; > +} > + > +int imx_drm_gem_dumb_map_offset(struct drm_file *file_priv, > + struct drm_device *drm, uint32_t handle, uint64_t *offset) > +{ > + struct imx_drm_gem_obj *imx_drm_gem_obj; > + struct drm_gem_object *obj; > + > + mutex_lock(&drm->struct_mutex); > + > + obj = drm_gem_object_lookup(drm, file_priv, handle); > + if (!obj) { > + dev_err(drm->dev, "failed to lookup gem object\n"); > + mutex_unlock(&drm->struct_mutex); > + return -EINVAL; > + } > + > + imx_drm_gem_obj = to_imx_drm_gem_obj(obj); > + > + *offset = get_gem_mmap_offset(&imx_drm_gem_obj->base); > + > + drm_gem_object_unreference(obj); > + > + mutex_unlock(&drm->struct_mutex); > + > + return 0; > +} > + > +int imx_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) > +{ > + struct drm_gem_object *obj = vma->vm_private_data; > + struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj); > + struct drm_device *dev = obj->dev; > + unsigned long pfn; > + pgoff_t page_offset; > + int ret; > + > + page_offset = ((unsigned long)vmf->virtual_address - > + vma->vm_start) >> PAGE_SHIFT; > + > + mutex_lock(&dev->struct_mutex); > + > + pfn = (imx_drm_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset; > + > + ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); > + > + mutex_unlock(&dev->struct_mutex); > + > + return convert_to_vm_err_msg(ret); > +} > + > +int imx_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) > +{ > + int ret; > + > + ret = drm_gem_mmap(filp, vma); > + if (ret) > + return ret; > + > + vma->vm_flags &= ~VM_PFNMAP; > + vma->vm_flags |= VM_MIXEDMAP; > + > + return ret; > +} > + > + > +int imx_drm_gem_dumb_destroy(struct drm_file *file_priv, > + struct drm_device *dev, unsigned int handle) > +{ > + return drm_gem_handle_delete(file_priv, handle); > +} > diff --git a/drivers/gpu/drm/imx/imx-lcdc-crtc.c b/drivers/gpu/drm/imx/imx-lcdc-crtc.c > new file mode 100644 > index 0000000..e77c015 > --- /dev/null > +++ b/drivers/gpu/drm/imx/imx-lcdc-crtc.c > @@ -0,0 +1,517 @@ > +/* > + * i.MX LCDC crtc driver > + * > + * Copyright (C) 2012 Sascha Hauer, Pengutronix > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + */ > +#include <linux/device.h> > +#include <linux/platform_device.h> > +#include <drm/drmP.h> > +#include <drm/drm_fb_helper.h> > +#include <drm/drm_crtc_helper.h> > +#include <linux/fb.h> > +#include <linux/clk.h> > +#include <asm/fb.h> > +#include <linux/module.h> > +#include <mach/hardware.h> > +#include <mach/imxfb.h> > +#include <generated/mach-types.h> > + > +#include "imx-drm.h" > + > +#define LCDC_SSA 0x00 > +#define LCDC_SIZE 0x04 > +#define LCDC_VPW 0x08 > +#define LCDC_CPOS 0x0C > +#define LCDC_LCWHB 0x10 > +#define LCDC_LCHCC 0x14 > +#define LCDC_PCR 0x18 > +#define LCDC_HCR 0x1C > +#define LCDC_VCR 0x20 > +#define LCDC_POS 0x24 > +#define LCDC_LSCR1 0x28 > +#define LCDC_PWMR 0x2C > +#define LCDC_DMACR 0x30 > +#define LCDC_RMCR 0x34 > +#define LCDC_LCDICR 0x38 > +#define LCDC_LIER 0x3c > +#define LCDC_LISR 0x40 > + > +#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20) > + > +#define YMAX_MASK (cpu_is_mx1() ? 0x1ff : 0x3ff) > +#define SIZE_YMAX(y) ((y) & YMAX_MASK) > + > +#define VPW_VPW(x) ((x) & 0x3ff) > + > +#define HCR_H_WIDTH(x) (((x) & 0x3f) << 26) > +#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8) > +#define HCR_H_WAIT_2(x) ((x) & 0xff) > + > +#define VCR_V_WIDTH(x) (((x) & 0x3f) << 26) > +#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8) > +#define VCR_V_WAIT_2(x) ((x) & 0xff) > + > +#define RMCR_LCDC_EN_MX1 (1 << 1) > + > +#define RMCR_SELF_REF (1 << 0) > + > +#define LIER_EOF (1 << 1) > + > +struct imx_crtc { > + struct drm_crtc base; > + struct imx_drm_crtc *imx_drm_crtc; > + int di_no; > + int enabled; > + void __iomem *regs; > + u32 pwmr; > + u32 lscr1; > + u32 dmacr; > + u32 pcr; > + struct clk *clk; > + struct device *dev; > + int vblank_enable; > + > + struct drm_pending_vblank_event *page_flip_event; > + struct drm_framebuffer *newfb; > +}; > + > +#define to_imx_crtc(x) container_of(x, struct imx_crtc, base) > + > +static void imx_crtc_load_lut(struct drm_crtc *crtc) > +{ > +} > + > +#define PCR_BPIX_8 (3 << 25) > +#define PCR_BPIX_12 (4 << 25) > +#define PCR_BPIX_16 (5 << 25) > +#define PCR_BPIX_18 (6 << 25) > +#define PCR_END_SEL (1 << 18) > +#define PCR_END_BYTE_SWAP (1 << 17) > + > +const char *fourcc_to_str(u32 fourcc) > +{ > + static char buf[5]; > + > + *(u32 *)buf = fourcc; > + buf[4] = 0; > + > + return buf; > +} > + > +static int imx_drm_crtc_set(struct drm_crtc *crtc, > + struct drm_display_mode *mode) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + struct drm_framebuffer *fb = crtc->fb; > + int lower_margin = mode->vsync_start - mode->vdisplay; > + int upper_margin = mode->vtotal - mode->vsync_end; > + int vsync_len = mode->vsync_end - mode->vsync_start; > + int hsync_len = mode->hsync_end - mode->hsync_start; > + int right_margin = mode->hsync_start - mode->hdisplay; > + int left_margin = mode->htotal - mode->hsync_end; > + unsigned long lcd_clk; > + u32 pcr; > + > + lcd_clk = clk_get_rate(imx_crtc->clk) / 1000; > + > + if (!mode->clock) > + return -EINVAL; > + > + pcr = DIV_ROUND_CLOSEST(lcd_clk, mode->clock); > + if (--pcr > 0x3f) > + pcr = 0x3f; > + > + switch (fb->pixel_format) { > + case DRM_FORMAT_XRGB8888: > + case DRM_FORMAT_ARGB8888: > + pcr |= PCR_BPIX_18; > + pcr |= PCR_END_SEL | PCR_END_BYTE_SWAP; > + break; > + case DRM_FORMAT_RGB565: > + if (cpu_is_mx1()) > + pcr |= PCR_BPIX_12; > + else > + pcr |= PCR_BPIX_16; > + break; > + case DRM_FORMAT_RGB332: > + pcr |= PCR_BPIX_8; > + break; > + default: > + dev_err(imx_crtc->dev, "unsupported pixel format %s\n", > + fourcc_to_str(fb->pixel_format)); > + return -EINVAL; > + } > + > + /* add sync polarities */ > + pcr |= imx_crtc->pcr & ~(0x3f | (7 << 25)); > + > + dev_dbg(imx_crtc->dev, > + "xres=%d hsync_len=%d left_margin=%d right_margin=%d\n", > + mode->hdisplay, hsync_len, > + left_margin, right_margin); > + dev_dbg(imx_crtc->dev, > + "yres=%d vsync_len=%d upper_margin=%d lower_margin=%d\n", > + mode->vdisplay, vsync_len, > + upper_margin, lower_margin); > + > + writel(VPW_VPW(mode->hdisplay * fb->bits_per_pixel / 8 / 4), > + imx_crtc->regs + LCDC_VPW); > + > + writel(HCR_H_WIDTH(hsync_len - 1) | > + HCR_H_WAIT_1(right_margin - 1) | > + HCR_H_WAIT_2(left_margin - 3), > + imx_crtc->regs + LCDC_HCR); > + > + writel(VCR_V_WIDTH(vsync_len) | > + VCR_V_WAIT_1(lower_margin) | > + VCR_V_WAIT_2(upper_margin), > + imx_crtc->regs + LCDC_VCR); > + > + writel(SIZE_XMAX(mode->hdisplay) | SIZE_YMAX(mode->vdisplay), > + imx_crtc->regs + LCDC_SIZE); > + > + writel(pcr, imx_crtc->regs + LCDC_PCR); > + writel(imx_crtc->pwmr, imx_crtc->regs + LCDC_PWMR); > + writel(imx_crtc->lscr1, imx_crtc->regs + LCDC_LSCR1); > + /* reset default */ > + writel(0x00040060, imx_crtc->regs + LCDC_DMACR); > + > + return 0; > +} > + > +static int imx_drm_set_base(struct drm_crtc *crtc, int x, int y) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + struct imx_drm_buf_entry *entry; > + struct drm_framebuffer *fb = crtc->fb; > + unsigned long phys; > + > + entry = imx_drm_fb_get_buf(fb); > + if (!entry) > + return -EFAULT; > + > + phys = entry->paddr; > + phys += x * (fb->bits_per_pixel >> 3); > + phys += y * fb->pitches[0]; > + > + dev_dbg(imx_crtc->dev, "%s: phys: 0x%lx\n", __func__, phys); > + dev_dbg(imx_crtc->dev, "%s: xy: %dx%d\n", __func__, x, y); > + > + writel(phys, imx_crtc->regs + LCDC_SSA); > + > + return 0; > +} > + > +static int imx_crtc_mode_set(struct drm_crtc *crtc, > + struct drm_display_mode *mode, > + struct drm_display_mode *adjusted_mode, > + int x, int y, > + struct drm_framebuffer *old_fb) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + > + imx_drm_set_base(crtc, x, y); > + > + dev_dbg(imx_crtc->dev, "mode->hdisplay: %d\n", mode->hdisplay); > + dev_dbg(imx_crtc->dev, "mode->vdisplay: %d\n", mode->vdisplay); > + > + return imx_drm_crtc_set(crtc, mode); > +} > + > +static void imx_crtc_enable(struct imx_crtc *imx_crtc) > +{ > + if (!imx_crtc->enabled) > + clk_enable(imx_crtc->clk); > + imx_crtc->enabled = 1; > +} > + > +static void imx_crtc_disable(struct imx_crtc *imx_crtc) > +{ > + if (imx_crtc->enabled) > + clk_disable(imx_crtc->clk); > + imx_crtc->enabled = 0; > +} > + > +static void imx_crtc_dpms(struct drm_crtc *crtc, int mode) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + > + dev_dbg(imx_crtc->dev, "%s mode: %d\n", __func__, mode); > + > + switch (mode) { > + case DRM_MODE_DPMS_ON: > + imx_crtc_enable(imx_crtc); > + break; > + default: > + imx_crtc_disable(imx_crtc); > + break; > + } > +} > + > +static bool imx_crtc_mode_fixup(struct drm_crtc *crtc, > + struct drm_display_mode *mode, > + struct drm_display_mode *adjusted_mode) > +{ > + return true; > +} > + > +static void imx_crtc_prepare(struct drm_crtc *crtc) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + > + imx_crtc_disable(imx_crtc); > +} > + > +static void imx_crtc_commit(struct drm_crtc *crtc) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + > + imx_crtc_enable(imx_crtc); > +} > + > +static struct drm_crtc_helper_funcs imx_helper_funcs = { > + .dpms = imx_crtc_dpms, > + .mode_fixup = imx_crtc_mode_fixup, > + .mode_set = imx_crtc_mode_set, > + .prepare = imx_crtc_prepare, > + .commit = imx_crtc_commit, > + .load_lut = imx_crtc_load_lut, > +}; > + > +static void imx_drm_handle_pageflip(struct imx_crtc *imx_crtc) > +{ > + struct drm_pending_vblank_event *e; > + struct timeval now; > + unsigned long flags; > + struct drm_device *drm = imx_crtc->base.dev; > + > + spin_lock_irqsave(&drm->event_lock, flags); > + > + e = imx_crtc->page_flip_event; > + > + if (!e) { > + spin_unlock_irqrestore(&drm->event_lock, flags); > + return; > + } > + > + do_gettimeofday(&now); > + e->event.sequence = 0; > + e->event.tv_sec = now.tv_sec; > + e->event.tv_usec = now.tv_usec; > + imx_crtc->page_flip_event = NULL; > + > + list_add_tail(&e->base.link, &e->base.file_priv->event_list); > + > + wake_up_interruptible(&e->base.file_priv->event_wait); > + > + spin_unlock_irqrestore(&drm->event_lock, flags); > +} > + > +static int imx_crtc_enable_vblank(struct drm_crtc *crtc) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + > + writel(LIER_EOF, imx_crtc->regs + LCDC_LIER); > + > + return 0; > +} > + > +static void imx_crtc_disable_vblank(struct drm_crtc *crtc) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + > + writel(0, imx_crtc->regs + LCDC_LIER); > +} > + > +static irqreturn_t imx_irq_handler(int irq, void *dev_id) > +{ > + struct imx_crtc *imx_crtc = dev_id; > + struct drm_device *drm = imx_crtc->base.dev; > + > + /* Acknowledge interrupt */ > + readl(imx_crtc->regs + LCDC_LISR); > + > + drm_handle_vblank(drm, 0); > + > + if (imx_crtc->newfb) { > + imx_crtc->base.fb = imx_crtc->newfb; > + imx_crtc->newfb = NULL; > + imx_drm_set_base(&imx_crtc->base, 0, 0); > + imx_drm_handle_pageflip(imx_crtc); > + imx_drm_crtc_vblank_put(imx_crtc->imx_drm_crtc); > + } > + > + return IRQ_HANDLED; > +} > + > +static int imx_page_flip(struct drm_crtc *crtc, > + struct drm_framebuffer *fb, > + struct drm_pending_vblank_event *event) > +{ > + struct imx_crtc *imx_crtc = to_imx_crtc(crtc); > + > + if (imx_crtc->newfb) > + return -EBUSY; > + > + imx_crtc->newfb = fb; > + imx_crtc->page_flip_event = event; > + imx_drm_crtc_vblank_get(imx_crtc->imx_drm_crtc); > + > + return 0; > +} > + > +static const struct drm_crtc_funcs imx_crtc_funcs = { > + .page_flip = imx_page_flip, > +}; > + > +static const struct imx_drm_crtc_helper_funcs imx_imx_drm_helper = { > + .enable_vblank = imx_crtc_enable_vblank, > + .disable_vblank = imx_crtc_disable_vblank, > +}; > + > +#define DRIVER_NAME "imx-lcdc-crtc" > + > +/* > + * the pcr bits to be allowed to set in platform data > + */ > +#define PDATA_PCR (PCR_PIXPOL | PCR_FLMPOL | PCR_LPPOL | \ > + PCR_CLKPOL | PCR_OEPOL | PCR_TFT | PCR_COLOR | \ > + PCR_PBSIZ_8 | PCR_ACD(0x7f) | PCR_ACD_SEL | \ > + PCR_SCLK_SEL | PCR_SHARP) > + > +static int __devinit imx_crtc_probe(struct platform_device *pdev) > +{ > + struct imx_crtc *imx_crtc; > + struct resource *res; > + int ret, irq; > + u32 pcr_value = 0xf00080c0; > + u32 lscr1_value = 0x00120300; > + u32 pwmr_value = 0x00a903ff; > + > + imx_crtc = devm_kzalloc(&pdev->dev, sizeof(*imx_crtc), GFP_KERNEL); > + if (!imx_crtc) > + return -ENOMEM; > + > + imx_crtc->dev = &pdev->dev; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + if (!res) > + return -ENODEV; > + > + res = devm_request_mem_region(&pdev->dev, res->start, > + resource_size(res), DRIVER_NAME); > + if (!res) > + return -EBUSY; > + > + imx_crtc->regs = devm_ioremap(&pdev->dev, res->start, > + resource_size(res)); > + if (!imx_crtc->regs) { > + dev_err(&pdev->dev, "Cannot map frame buffer registers\n"); > + return -EBUSY; > + } > + > + irq = platform_get_irq(pdev, 0); > + ret = devm_request_irq(&pdev->dev, irq, imx_irq_handler, 0, "imx_drm", > + imx_crtc); > + if (ret < 0) { > + dev_err(&pdev->dev, "irq request failed with %d\n", ret); > + return ret; > + } > + > + imx_crtc->clk = clk_get(&pdev->dev, NULL); > + if (IS_ERR(imx_crtc->clk)) { > + ret = PTR_ERR(imx_crtc->clk); > + dev_err(&pdev->dev, "unable to get clock: %d\n", ret); > + return ret; > + } > + > + clk_prepare_enable(imx_crtc->clk); > + imx_crtc->enabled = 1; > + > + platform_set_drvdata(pdev, imx_crtc); > + > + imx_crtc->pcr = pcr_value & PDATA_PCR; > + > + if (imx_crtc->pcr != pcr_value) > + dev_err(&pdev->dev, "invalid bits set in pcr: 0x%08x\n", > + pcr_value & ~PDATA_PCR); > + > + imx_crtc->lscr1 = lscr1_value; > + imx_crtc->pwmr = pwmr_value; > + > + ret = imx_drm_add_crtc(&imx_crtc->base, > + &imx_crtc->imx_drm_crtc, > + &imx_crtc_funcs, &imx_helper_funcs, > + &imx_imx_drm_helper, THIS_MODULE); > + if (ret) > + goto err_init; > + > + dev_info(&pdev->dev, "probed\n"); > + > + return 0; > + > +err_init: > + clk_disable_unprepare(imx_crtc->clk); > + clk_put(imx_crtc->clk); > + > + return ret; > +} > + > +static int __devexit imx_crtc_remove(struct platform_device *pdev) > +{ > + struct imx_crtc *imx_crtc = platform_get_drvdata(pdev); > + > + imx_drm_remove_crtc(imx_crtc->imx_drm_crtc); > + > + writel(0, imx_crtc->regs + LCDC_LIER); > + > + clk_disable_unprepare(imx_crtc->clk); > + clk_put(imx_crtc->clk); > + > + platform_set_drvdata(pdev, NULL); > + > + return 0; > +} > + > +static const struct of_device_id imx_lcdc_dt_ids[] = { > + { .compatible = "fsl,imx1-lcdc", .data = NULL, }, > + { .compatible = "fsl,imx21-lcdc", .data = NULL, }, > + { /* sentinel */ } > +}; > + > +static struct platform_driver imx_crtc_driver = { > + .remove = __devexit_p(imx_crtc_remove), > + .probe = imx_crtc_probe, > + .driver = { > + .name = DRIVER_NAME, > + .owner = THIS_MODULE, > + .of_match_table = imx_lcdc_dt_ids, > + }, > +}; > + > +static int __init imx_lcdc_init(void) > +{ > + return platform_driver_register(&imx_crtc_driver); > +} > + > +static void __exit imx_lcdc_exit(void) > +{ > + platform_driver_unregister(&imx_crtc_driver); > +} > + > +module_init(imx_lcdc_init); > +module_exit(imx_lcdc_exit) > + > +MODULE_DESCRIPTION("Freescale i.MX framebuffer driver"); > +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); > +MODULE_LICENSE("GPL"); > diff --git a/drivers/gpu/drm/imx/imx-parallel-display.c b/drivers/gpu/drm/imx/imx-parallel-display.c > new file mode 100644 > index 0000000..8c96113 > --- /dev/null > +++ b/drivers/gpu/drm/imx/imx-parallel-display.c > @@ -0,0 +1,228 @@ > +/* > + * i.MX drm driver - parallel display implementation > + * > + * Copyright (C) 2012 Sascha Hauer, Pengutronix > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, > + * MA 02110-1301, USA. > + */ > + > +#include <linux/module.h> > +#include <drm/drmP.h> > +#include <drm/drm_fb_helper.h> > +#include <drm/drm_crtc_helper.h> > + > +#include "imx-drm.h" > + > +#define con_to_imxpd(x) container_of(x, struct imx_parallel_display, connector) > +#define enc_to_imxpd(x) container_of(x, struct imx_parallel_display, encoder) > + > +struct imx_parallel_display { > + struct drm_connector connector; > + struct imx_drm_connector *imx_drm_connector; > + struct drm_encoder encoder; > + struct imx_drm_encoder *imx_drm_encoder; > + struct device *dev; > + void *edid; > + int edid_len; > +}; > + > +static enum drm_connector_status imx_pd_connector_detect(struct drm_connector *connector, > + bool force) > +{ > + return connector_status_connected; > +} > + > +static void imx_pd_connector_destroy(struct drm_connector *connector) > +{ > + /* do not free here */ > +} > + > +static int imx_pd_connector_get_modes(struct drm_connector *connector) > +{ > + struct imx_parallel_display *imxpd = con_to_imxpd(connector); > + int ret; > + > + drm_mode_connector_update_edid_property(connector, imxpd->edid); > + ret = drm_add_edid_modes(connector, imxpd->edid); > + connector->display_info.raw_edid = NULL; > + > + return ret; > +} > + > +static int imx_pd_connector_mode_valid(struct drm_connector *connector, > + struct drm_display_mode *mode) > +{ > + return 0; > +} > + > +static struct drm_encoder *imx_pd_connector_best_encoder(struct drm_connector *connector) > +{ > + struct imx_parallel_display *imxpd = con_to_imxpd(connector); > + > + return &imxpd->encoder; > +} > + > +static void imx_pd_encoder_dpms(struct drm_encoder *encoder, int mode) > +{ > +} > + > +static bool imx_pd_encoder_mode_fixup(struct drm_encoder *encoder, > + struct drm_display_mode *mode, > + struct drm_display_mode *adjusted_mode) > +{ > + return true; > +} > + > +static void imx_pd_encoder_prepare(struct drm_encoder *encoder) > +{ > +} > + > +static void imx_pd_encoder_commit(struct drm_encoder *encoder) > +{ > +} > + > +static void imx_pd_encoder_mode_set(struct drm_encoder *encoder, > + struct drm_display_mode *mode, > + struct drm_display_mode *adjusted_mode) > +{ > +} > + > +static void imx_pd_encoder_disable(struct drm_encoder *encoder) > +{ > +} > + > +static void imx_pd_encoder_destroy(struct drm_encoder *encoder) > +{ > + /* do not free here */ > +} > + > +struct drm_connector_funcs imx_pd_connector_funcs = { > + .dpms = drm_helper_connector_dpms, > + .fill_modes = drm_helper_probe_single_connector_modes, > + .detect = imx_pd_connector_detect, > + .destroy = imx_pd_connector_destroy, > +}; > + > +struct drm_connector_helper_funcs imx_pd_connector_helper_funcs = { > + .get_modes = imx_pd_connector_get_modes, > + .best_encoder = imx_pd_connector_best_encoder, > + .mode_valid = imx_pd_connector_mode_valid, > +}; > + > +static struct drm_encoder_funcs imx_pd_encoder_funcs = { > + .destroy = imx_pd_encoder_destroy, > +}; > + > +static struct drm_encoder_helper_funcs imx_pd_encoder_helper_funcs = { > + .dpms = imx_pd_encoder_dpms, > + .mode_fixup = imx_pd_encoder_mode_fixup, > + .prepare = imx_pd_encoder_prepare, > + .commit = imx_pd_encoder_commit, > + .mode_set = imx_pd_encoder_mode_set, > + .disable = imx_pd_encoder_disable, > +}; > + > +static int imx_pd_register(struct imx_parallel_display *imxpd) > +{ > + int ret; > + > + drm_mode_connector_attach_encoder(&imxpd->connector, &imxpd->encoder); > + > + imxpd->connector.funcs = &imx_pd_connector_funcs; > + imxpd->encoder.funcs = &imx_pd_encoder_funcs; > + > + drm_encoder_helper_add(&imxpd->encoder, &imx_pd_encoder_helper_funcs); > + ret = imx_drm_add_encoder(&imxpd->encoder, &imxpd->imx_drm_encoder, THIS_MODULE); > + if (ret) { > + dev_err(imxpd->dev, "adding encoder failed with %d\n", ret); > + return ret; > + } > + > + drm_connector_helper_add(&imxpd->connector, &imx_pd_connector_helper_funcs); > + > + ret = imx_drm_add_connector(&imxpd->connector, &imxpd->imx_drm_connector, > + THIS_MODULE); > + if (ret) { > + imx_drm_remove_encoder(imxpd->imx_drm_encoder); > + dev_err(imxpd->dev, "adding connector failed with %d\n", ret); > + return ret; > + } > + > + imxpd->connector.encoder = &imxpd->encoder; > + > + return 0; > +} > + > +static int __devinit imx_pd_probe(struct platform_device *pdev) > +{ > + struct device_node *np = pdev->dev.of_node; > + const u8 *edidp; > + struct imx_parallel_display *imxpd; > + int ret; > + > + imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL); > + if (!imxpd) > + return -ENOMEM; > + > + edidp = of_get_property(np, "edid", &imxpd->edid_len); > + > + imxpd->edid = kmemdup(edidp, imxpd->edid_len, GFP_KERNEL); > + imxpd->encoder.possible_crtcs = 0x1; > + imxpd->encoder.possible_clones = 0x1; > + imxpd->dev = &pdev->dev; > + > + ret = imx_pd_register(imxpd); > + if (ret) > + return ret; > + > + platform_set_drvdata(pdev, imxpd); > + > + return 0; > +} > + > +static int __devexit imx_pd_remove(struct platform_device *pdev) > +{ > + struct imx_parallel_display *imxpd = platform_get_drvdata(pdev); > + struct drm_connector *connector = &imxpd->connector; > + struct drm_encoder *encoder = &imxpd->encoder; > + > + drm_mode_connector_detach_encoder(connector, encoder); > + > + imx_drm_remove_connector(imxpd->imx_drm_connector); > + imx_drm_remove_encoder(imxpd->imx_drm_encoder); > + > + return 0; > +} > + > +static const struct of_device_id imx_pd_dt_ids[] = { > + { .compatible = "fsl,imx-parallel-display", .data = NULL, }, > + { /* sentinel */ } > +}; > + > +static struct platform_driver imx_pd_driver = { > + .probe = imx_pd_probe, > + .remove = __devexit_p(imx_pd_remove), > + .driver = { > + .of_match_table = imx_pd_dt_ids, > + .name = "imx-parallel-display", > + .owner = THIS_MODULE, > + }, > +}; > + > +module_platform_driver(imx_pd_driver); > + > +MODULE_DESCRIPTION("i.MX parallel display driver"); > +MODULE_AUTHOR("Sascha Hauer, Pengutronix"); > +MODULE_LICENSE("GPL"); > -- > 1.7.10 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 1/2] DRM: add Freescale i.MX LCDC driver 2012-05-22 21:28 ` Rob Clark @ 2012-05-23 7:47 ` Sascha Hauer 2012-05-23 8:37 ` Lars-Peter Clausen 0 siblings, 1 reply; 42+ messages in thread From: Sascha Hauer @ 2012-05-23 7:47 UTC (permalink / raw) To: Rob Clark; +Cc: linux-arm-kernel, dri-devel Hi Rob, On Tue, May 22, 2012 at 03:28:20PM -0600, Rob Clark wrote: > just a few comments from a cursory review.. I need a bit more time > for a more in-depth review but that won't be tonight so I thought I'd > send what I have so far.. Thanks for this. > > +++ b/drivers/gpu/drm/imx/Kconfig > > @@ -0,0 +1,18 @@ > > +config DRM_IMX > > + tristate "DRM Support for Freescale i.MX" > > + select DRM_KMS_HELPER > > + depends on DRM && ARCH_MXC > > + > > +config DRM_IMX_FB_HELPER > > + tristate "provide legacy framebuffer /dev/fb0" > > + depends on DRM_IMX > > + > > +config DRM_IMX_LCDC > > + tristate "DRM Support for Freescale i.MX1 and i.MX2" > > + depends on DRM_IMX > > + help > > + Choose this if you have a i.MX1, i.MX21, i.MX25 or i.MX27 processor. > > do you have something like cpu_is_imx2() type macros? It would be > preferable not to have a compile time config option for building for > certain hw versions. Ie. on OMAP we could do something like 'if > (cpu_is_omap3xxx()) { ... }' if there was something that needed to be > done different on omap3 family of devices. This way you could choose > to build a kernel supporting either a single omap variants, or all > omap variants. Yes, we have cpu_is_* macros. I don't see though why we should use them here. The result of DRM_IMX_LCDC will be a platform driver for which a suitable device exists only on the correct SoCs. There will be a second DRM_IMX_IPU option next to this one for the newer i.MX SoCs which will be a second platform driver. > > + > > + /* > > + * without file_priv we are called from imx_drm_fbdev_create in which > > + * case we only create a framebuffer without a handle. > > + */ > > + if (!file_priv) { > > + struct imx_drm_buf_entry *entry; > > + > > + entry = imx_drm_buf_create(dev, size); > > + if (IS_ERR(entry)) { > > + ret = PTR_ERR(entry); > > + goto err_buffer; > > + } > > + > > + imx_drm_fb->entry = entry; > > + } else { > > + obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handles[0]); > > + if (!obj) { > > + ret = -EINVAL; > > + goto err_buffer; > > + } > > + > > + imx_drm_fb->imx_drm_gem_obj = to_imx_drm_gem_obj(obj); > > + > > + drm_gem_object_unreference_unlocked(obj); > > > the fb probably should hold the reference to the GEM obj until it is > deleted.. so you don't end up freeing the buffer you are scanning out > until you are done scanning it out. Possibly this gets a bit more > straightforward if you don't have to special case the default/fbcon > framebuffer? > > IIRC, Laurent had sent a patch recently to fix the same issue in the > exynos driver. Yes, just for reference, here is a link: http://permalink.gmane.org/gmane.comp.video.dri.devel/69203 Will fix this. > > + > > +static int imx_drm_gem_mmap_buffer(struct file *filp, > > + struct vm_area_struct *vma) > > +{ > > + struct drm_gem_object *obj = filp->private_data; > > + struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj); > > + struct imx_drm_buf_entry *entry; > > + unsigned long pfn, vm_size; > > + > > + vma->vm_flags |= VM_IO | VM_RESERVED; > > + > > + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); > > pgprot_writecombine()? copied from the exynos driver. The exynos driver recently gained support for different cache attribute flags and I could do the same. I would prefer not to even have to think about it by using some generic code here instead of duplicating other peoples bugs. Do you think it's possible to share this code as suggested by Lars? Every SoC not having a IOMMU could share the same code here, it's just not clear to me how we can put this in a form that is acceptable upstream. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 1/2] DRM: add Freescale i.MX LCDC driver 2012-05-23 7:47 ` Sascha Hauer @ 2012-05-23 8:37 ` Lars-Peter Clausen 2012-05-23 9:09 ` Daniel Vetter 0 siblings, 1 reply; 42+ messages in thread From: Lars-Peter Clausen @ 2012-05-23 8:37 UTC (permalink / raw) To: Sascha Hauer; +Cc: dri-devel, linux-arm-kernel, Rob Clark [...] >>> + >>> +static int imx_drm_gem_mmap_buffer(struct file *filp, >>> + struct vm_area_struct *vma) >>> +{ >>> + struct drm_gem_object *obj = filp->private_data; >>> + struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj); >>> + struct imx_drm_buf_entry *entry; >>> + unsigned long pfn, vm_size; >>> + >>> + vma->vm_flags |= VM_IO | VM_RESERVED; >>> + >>> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); >> >> pgprot_writecombine()? > > copied from the exynos driver. The exynos driver recently gained support > for different cache attribute flags and I could do the same. I would > prefer not to even have to think about it by using some generic code > here instead of duplicating other peoples bugs. > > Do you think it's possible to share this code as suggested by Lars? > Every SoC not having a IOMMU could share the same code here, it's just > not clear to me how we can put this in a form that is acceptable > upstream. I may have missed this in the previous discussion. But why can't we put the gem handling code in the toplevel drm folder, give it a config symbol and let drivers which want to use the code select the config symbol? I think the main concern was about introducing a new intermediate layer, but the "simple" gem support would really just a set of helper functions. Thanks, - Lars ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 1/2] DRM: add Freescale i.MX LCDC driver 2012-05-23 8:37 ` Lars-Peter Clausen @ 2012-05-23 9:09 ` Daniel Vetter 0 siblings, 0 replies; 42+ messages in thread From: Daniel Vetter @ 2012-05-23 9:09 UTC (permalink / raw) To: Lars-Peter Clausen; +Cc: linux-arm-kernel, dri-devel, Rob Clark On Wed, May 23, 2012 at 10:37:58AM +0200, Lars-Peter Clausen wrote: > [...] > >>> + > >>> +static int imx_drm_gem_mmap_buffer(struct file *filp, > >>> + struct vm_area_struct *vma) > >>> +{ > >>> + struct drm_gem_object *obj = filp->private_data; > >>> + struct imx_drm_gem_obj *imx_drm_gem_obj = to_imx_drm_gem_obj(obj); > >>> + struct imx_drm_buf_entry *entry; > >>> + unsigned long pfn, vm_size; > >>> + > >>> + vma->vm_flags |= VM_IO | VM_RESERVED; > >>> + > >>> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); > >> > >> pgprot_writecombine()? > > > > copied from the exynos driver. The exynos driver recently gained support > > for different cache attribute flags and I could do the same. I would > > prefer not to even have to think about it by using some generic code > > here instead of duplicating other peoples bugs. > > > > Do you think it's possible to share this code as suggested by Lars? > > Every SoC not having a IOMMU could share the same code here, it's just > > not clear to me how we can put this in a form that is acceptable > > upstream. > > I may have missed this in the previous discussion. But why can't we put the > gem handling code in the toplevel drm folder, give it a config symbol and > let drivers which want to use the code select the config symbol? I think the > main concern was about introducing a new intermediate layer, but the > "simple" gem support would really just a set of helper functions. Same for the kms stuff. Me&Dave shot at sdrm because it introduces an intermediate layer, not because adding some common code for simple drm/kms drivers is pointless. That is very much welcome ;-) -Daniel -- Daniel Vetter Mail: daniel@ffwll.ch Mobile: +41 (0)79 365 57 48 ^ permalink raw reply [flat|nested] 42+ messages in thread
* [PATCH 2/2] pcm038 lcdc support 2012-05-18 12:27 (unknown), Sascha Hauer 2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer @ 2012-05-18 12:27 ` Sascha Hauer 2012-05-18 14:03 ` Adam Jackson 2012-05-22 14:06 ` Lars-Peter Clausen 2 siblings, 1 reply; 42+ messages in thread From: Sascha Hauer @ 2012-05-18 12:27 UTC (permalink / raw) To: dri-devel; +Cc: Sascha Hauer, linux-arm-kernel Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- arch/arm/boot/dts/imx27-phytec-phycore.dts | 39 ++++++++++++++++++++++++++++ arch/arm/boot/dts/imx27.dtsi | 7 +++++ arch/arm/mach-imx/clock-imx27.c | 1 + 3 files changed, 47 insertions(+) diff --git a/arch/arm/boot/dts/imx27-phytec-phycore.dts b/arch/arm/boot/dts/imx27-phytec-phycore.dts index a51a08f..bdb7547 100644 --- a/arch/arm/boot/dts/imx27-phytec-phycore.dts +++ b/arch/arm/boot/dts/imx27-phytec-phycore.dts @@ -20,6 +20,41 @@ reg = <0x0 0x0>; }; + baseboard { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + + display { + compatible = "fsl,imx-parallel-display"; + edid = [00 ff ff ff ff ff ff 00 4c 2d 6c 03 36 32 49 4b + 0f 13 01 03 80 37 22 a0 2a fe 21 a8 53 37 ae 24 + 11 50 54 + + /* est timings */ + 00 00 00 + + /* std timings */ + 00 00 + 00 00 + 00 00 + 00 00 + 00 00 + 00 00 + 00 00 + 00 00 + + /* detailed timings */ + 05 0D 20 A0 30 58 1C 20 28 20 14 00 26 57 21 00 00 1E + 00 00 00 fd 00 32 4b 1b 51 11 00 0a 20 20 20 20 20 20 + 00 00 00 fc 00 53 79 6e 63 4d 61 73 74 65 72 0a 20 20 + 00 00 00 ff 00 48 39 58 53 34 30 30 34 34 32 0a 20 20 + 00 20]; + + crtc = <&lcdc 0>; + }; + }; + soc { aipi@10000000 { /* aipi */ @@ -46,6 +81,10 @@ status = "okay"; }; + lcdc@10021000 { + status = "okay"; + }; + i2c@1001d000 { clock-frequency = <400000>; status = "okay"; diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi index bc5e7d5..eab9095 100644 --- a/arch/arm/boot/dts/imx27.dtsi +++ b/arch/arm/boot/dts/imx27.dtsi @@ -206,6 +206,13 @@ status = "disabled"; }; + lcdc: lcdc@10021000 { + compatible = "fsl,imx27-lcdc", "fsl,imx21-lcdc"; + reg = <0x10021000 0x4000>; + interrupts = <61>; + status = "enabled"; + }; + fec: fec@1002b000 { compatible = "fsl,imx27-fec"; reg = <0x1002b000 0x4000>; diff --git a/arch/arm/mach-imx/clock-imx27.c b/arch/arm/mach-imx/clock-imx27.c index 98e04f5..a393483 100644 --- a/arch/arm/mach-imx/clock-imx27.c +++ b/arch/arm/mach-imx/clock-imx27.c @@ -646,6 +646,7 @@ static struct clk_lookup lookups[] = { _REGISTER_CLOCK("imx27-cspi.1", NULL, cspi2_clk) _REGISTER_CLOCK("imx27-cspi.2", NULL, cspi3_clk) _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk) + _REGISTER_CLOCK("10021000.lcdc", NULL, lcdc_clk) _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk) _REGISTER_CLOCK("fsl-usb2-udc", "usb", usb_clk) _REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", usb_clk1) -- 1.7.10 ^ permalink raw reply related [flat|nested] 42+ messages in thread
* Re: [PATCH 2/2] pcm038 lcdc support 2012-05-18 12:27 ` [PATCH 2/2] pcm038 lcdc support Sascha Hauer @ 2012-05-18 14:03 ` Adam Jackson 2012-05-18 15:13 ` Sascha Hauer 0 siblings, 1 reply; 42+ messages in thread From: Adam Jackson @ 2012-05-18 14:03 UTC (permalink / raw) To: Sascha Hauer; +Cc: linux-arm-kernel, dri-devel [-- Attachment #1.1: Type: text/plain, Size: 1062 bytes --] On Fri, 2012-05-18 at 14:27 +0200, Sascha Hauer wrote: > + edid = [00 ff ff ff ff ff ff 00 4c 2d 6c 03 36 32 49 4b > + 0f 13 01 03 80 37 22 a0 2a fe 21 a8 53 37 ae 24 > + 11 50 54 > + > + /* est timings */ > + 00 00 00 > + > + /* std timings */ > + 00 00 > + 00 00 > + 00 00 > + 00 00 > + 00 00 > + 00 00 > + 00 00 > + 00 00 > + > + /* detailed timings */ > + 05 0D 20 A0 30 58 1C 20 28 20 14 00 26 57 21 00 00 1E > + 00 00 00 fd 00 32 4b 1b 51 11 00 0a 20 20 20 20 20 20 > + 00 00 00 fc 00 53 79 6e 63 4d 61 73 74 65 72 0a 20 20 > + 00 00 00 ff 00 48 39 58 53 34 30 30 34 34 32 0a 20 20 > + 00 20]; This EDID block claims to be a Samsung SyncMaster, which isn't really the right thing to do. The question is what to call it instead. Red Hat has a PNP ID we can use for virtual EDID blocks like this if we want, I'd want to set up a little database to keep track of them but that's pretty trivial. Also, empty standard timing fields are 01 01, not 00 00. - ajax [-- Attachment #1.2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 198 bytes --] [-- Attachment #2: Type: text/plain, Size: 159 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 2/2] pcm038 lcdc support 2012-05-18 14:03 ` Adam Jackson @ 2012-05-18 15:13 ` Sascha Hauer 2012-05-22 10:02 ` Dave Airlie 0 siblings, 1 reply; 42+ messages in thread From: Sascha Hauer @ 2012-05-18 15:13 UTC (permalink / raw) To: Adam Jackson; +Cc: linux-arm-kernel, dri-devel On Fri, May 18, 2012 at 10:03:54AM -0400, Adam Jackson wrote: > On Fri, 2012-05-18 at 14:27 +0200, Sascha Hauer wrote: > > > + edid = [00 ff ff ff ff ff ff 00 4c 2d 6c 03 36 32 49 4b > > + 0f 13 01 03 80 37 22 a0 2a fe 21 a8 53 37 ae 24 > > + 11 50 54 > > + > > + /* est timings */ > > + 00 00 00 > > + > > + /* std timings */ > > + 00 00 > > + 00 00 > > + 00 00 > > + 00 00 > > + 00 00 > > + 00 00 > > + 00 00 > > + 00 00 > > + > > + /* detailed timings */ > > + 05 0D 20 A0 30 58 1C 20 28 20 14 00 26 57 21 00 00 1E > > + 00 00 00 fd 00 32 4b 1b 51 11 00 0a 20 20 20 20 20 20 > > + 00 00 00 fc 00 53 79 6e 63 4d 61 73 74 65 72 0a 20 20 > > + 00 00 00 ff 00 48 39 58 53 34 30 30 34 34 32 0a 20 20 > > + 00 20]; > > This EDID block claims to be a Samsung SyncMaster, which isn't really > the right thing to do. The question is what to call it instead. Red > Hat has a PNP ID we can use for virtual EDID blocks like this if we > want, I'd want to set up a little database to keep track of them but > that's pretty trivial. Sorry, should have mentioned this in the commit log. This in fact is a hacked version of my office monitor. This patch is more meant as a usage example and not for upstream. I don't know yet if it's even acceptable to put edid data into the devicetree. I saw some discussion about it, but also about some generic display description, which I would prefer. BTW is there a more convenient tool than a hex editor around to generate edid data? I only found some windows tools > > Also, empty standard timing fields are 01 01, not 00 00. Good to know Thanks Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [PATCH 2/2] pcm038 lcdc support 2012-05-18 15:13 ` Sascha Hauer @ 2012-05-22 10:02 ` Dave Airlie 0 siblings, 0 replies; 42+ messages in thread From: Dave Airlie @ 2012-05-22 10:02 UTC (permalink / raw) To: Sascha Hauer; +Cc: dri-devel, linux-arm-kernel On Fri, May 18, 2012 at 4:13 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote: > On Fri, May 18, 2012 at 10:03:54AM -0400, Adam Jackson wrote: >> On Fri, 2012-05-18 at 14:27 +0200, Sascha Hauer wrote: >> >> > + edid = [00 ff ff ff ff ff ff 00 4c 2d 6c 03 36 32 49 4b >> > + 0f 13 01 03 80 37 22 a0 2a fe 21 a8 53 37 ae 24 >> > + 11 50 54 >> > + >> > + /* est timings */ >> > + 00 00 00 >> > + >> > + /* std timings */ >> > + 00 00 >> > + 00 00 >> > + 00 00 >> > + 00 00 >> > + 00 00 >> > + 00 00 >> > + 00 00 >> > + 00 00 >> > + >> > + /* detailed timings */ >> > + 05 0D 20 A0 30 58 1C 20 28 20 14 00 26 57 21 00 00 1E >> > + 00 00 00 fd 00 32 4b 1b 51 11 00 0a 20 20 20 20 20 20 >> > + 00 00 00 fc 00 53 79 6e 63 4d 61 73 74 65 72 0a 20 20 >> > + 00 00 00 ff 00 48 39 58 53 34 30 30 34 34 32 0a 20 20 >> > + 00 20]; >> >> This EDID block claims to be a Samsung SyncMaster, which isn't really >> the right thing to do. The question is what to call it instead. Red >> Hat has a PNP ID we can use for virtual EDID blocks like this if we >> want, I'd want to set up a little database to keep track of them but >> that's pretty trivial. > > Sorry, should have mentioned this in the commit log. This in fact is a > hacked version of my office monitor. This patch is more meant as a usage > example and not for upstream. I don't know yet if it's even acceptable > to put edid data into the devicetree. I saw some discussion about it, > but also about some generic display description, which I would prefer. > > BTW is there a more convenient tool than a hex editor around to generate > edid data? I only found some windows tools Some basic stuff in Documentation/EDID/ but yeah don't know of anything graphical for Linux. Dave. ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2012-05-18 12:27 (unknown), Sascha Hauer 2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer 2012-05-18 12:27 ` [PATCH 2/2] pcm038 lcdc support Sascha Hauer @ 2012-05-22 14:06 ` Lars-Peter Clausen 2012-05-23 8:12 ` Re: Sascha Hauer 2012-05-24 6:31 ` Re: Sascha Hauer 2 siblings, 2 replies; 42+ messages in thread From: Lars-Peter Clausen @ 2012-05-22 14:06 UTC (permalink / raw) To: Sascha Hauer; +Cc: linux-arm-kernel, dri-devel On 05/18/2012 02:27 PM, Sascha Hauer wrote: > Hi All, > > The following adds a drm/kms driver for the Freescale i.MX LCDC > controller. Most notable change to the last SDRM based version is that > the SDRM layer has been removed and the driver now is purely i.MX > specific. I hope that this is more acceptable now. > > Another change is that the probe is now devicetree based. For now I > took the easy way out and only put an edid blob into the devicetree. > I haven't documented the binding yet, I would add that when the rest > is considered ok. > > Comments very welcome. > Hi, I really liked the sdrm layer. At least some bits of it. I've been working on a "simple" DRM driver as well. The hardware has no fancy acceleration features, just a simple buffer and some scanout logic. I'm basically using the same gem buffer structure and the buffer is also allocated using dma_alloc_writecombine, which means we can probably share all of the GEM handling code and probably also most of the fbdev code. I also started with the Exynos GEM code as a template, but reworked it later to be more like the UDL code, which made it a bit more compact. I think it would be a good idea to put at least the GEM handling in some common code as I expect that we'll see more similar "simple" DRM drivers pop up. The code in question can be found at https://github.com/lclausen-adi/linux-2.6/commit/87a8fd6b98eeee317c7a486846cc8405d0bd68d8 Btw. the imx-drm.h is missing in your patch. - Lars > Thanks > Sascha > > ---------------------------------------------------------------- > Sascha Hauer (2): > DRM: add Freescale i.MX LCDC driver > pcm038 lcdc support > > arch/arm/boot/dts/imx27-phytec-phycore.dts | 39 ++ > arch/arm/boot/dts/imx27.dtsi | 7 + > arch/arm/mach-imx/clock-imx27.c | 1 + > drivers/gpu/drm/Kconfig | 2 + > drivers/gpu/drm/Makefile | 1 + > drivers/gpu/drm/imx/Kconfig | 18 + > drivers/gpu/drm/imx/Makefile | 8 + > drivers/gpu/drm/imx/imx-drm-core.c | 745 ++++++++++++++++++++++++++++ > drivers/gpu/drm/imx/imx-fb.c | 179 +++++++ > drivers/gpu/drm/imx/imx-fbdev.c | 275 ++++++++++ > drivers/gpu/drm/imx/imx-gem.c | 343 +++++++++++++ > drivers/gpu/drm/imx/imx-lcdc-crtc.c | 517 +++++++++++++++++++ > drivers/gpu/drm/imx/imx-parallel-display.c | 228 +++++++++ > 13 files changed, 2363 insertions(+) > create mode 100644 drivers/gpu/drm/imx/Kconfig > create mode 100644 drivers/gpu/drm/imx/Makefile > create mode 100644 drivers/gpu/drm/imx/imx-drm-core.c > create mode 100644 drivers/gpu/drm/imx/imx-fb.c > create mode 100644 drivers/gpu/drm/imx/imx-fbdev.c > create mode 100644 drivers/gpu/drm/imx/imx-gem.c > create mode 100644 drivers/gpu/drm/imx/imx-lcdc-crtc.c > create mode 100644 drivers/gpu/drm/imx/imx-parallel-display.c > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2012-05-22 14:06 ` Lars-Peter Clausen @ 2012-05-23 8:12 ` Sascha Hauer 2012-05-24 6:31 ` Re: Sascha Hauer 1 sibling, 0 replies; 42+ messages in thread From: Sascha Hauer @ 2012-05-23 8:12 UTC (permalink / raw) To: Lars-Peter Clausen; +Cc: linux-arm-kernel, dri-devel On Tue, May 22, 2012 at 04:06:41PM +0200, Lars-Peter Clausen wrote: > On 05/18/2012 02:27 PM, Sascha Hauer wrote: > > Hi All, > > > > The following adds a drm/kms driver for the Freescale i.MX LCDC > > controller. Most notable change to the last SDRM based version is that > > the SDRM layer has been removed and the driver now is purely i.MX > > specific. I hope that this is more acceptable now. > > > > Another change is that the probe is now devicetree based. For now I > > took the easy way out and only put an edid blob into the devicetree. > > I haven't documented the binding yet, I would add that when the rest > > is considered ok. > > > > Comments very welcome. > > > > Hi, > > I really liked the sdrm layer. At least some bits of it. I've been working > on a "simple" DRM driver as well. The hardware has no fancy acceleration > features, just a simple buffer and some scanout logic. I'm basically using > the same gem buffer structure and the buffer is also allocated using > dma_alloc_writecombine, which means we can probably share all of the GEM > handling code and probably also most of the fbdev code. I also started with > the Exynos GEM code as a template, but reworked it later to be more like the > UDL code, which made it a bit more compact. I think it would be a good idea > to put at least the GEM handling in some common code as I expect that we'll > see more similar "simple" DRM drivers pop up. I totally agree. Having to track other drivers for bug fixes to apply them on the own driver is not very convenient. As answered to Rob I do not really have a clue how to accomplish this. > > The code in question can be found at > https://github.com/lclausen-adi/linux-2.6/commit/87a8fd6b98eeee317c7a486846cc8405d0bd68d8 > > Btw. the imx-drm.h is missing in your patch. Oops, here it is for reference, will include it in the next round. #ifndef _IMX_DRM_H_ #define _IMX_DRM_H_ /** * User-desired buffer creation information structure. * * @size: requested size for the object. * - this size value would be page-aligned internally. * @flags: user request for setting memory type or cache attributes. * @handle: returned handle for the object. */ struct imx_drm_gem_create { unsigned int size; unsigned int flags; unsigned int handle; }; struct imx_drm_device; struct imx_drm_crtc; struct imx_drm_crtc_helper_funcs { int (*enable_vblank)(struct drm_crtc *crtc); void (*disable_vblank)(struct drm_crtc *crtc); }; int imx_drm_add_crtc(struct drm_crtc *crtc, struct imx_drm_crtc **new_crtc, const struct drm_crtc_funcs *crtc_funcs, const struct drm_crtc_helper_funcs *crtc_helper_funcs, const struct imx_drm_crtc_helper_funcs *ec_helper_funcs, struct module *owner); int imx_drm_remove_crtc(struct imx_drm_crtc *); int imx_drm_init_drm(struct platform_device *pdev, int preferred_bpp); int imx_drm_exit_drm(void); int imx_drm_crtc_vblank_get(struct imx_drm_crtc *imx_drm_crtc); void imx_drm_crtc_vblank_put(struct imx_drm_crtc *imx_drm_crtc); void imx_drm_handle_vblank(struct imx_drm_crtc *imx_drm_crtc); /* * imx drm buffer entry structure. * * @paddr: physical address of allocated memory. * @vaddr: kernel virtual address of allocated memory. * @size: size of allocated memory. */ struct imx_drm_buf_entry { dma_addr_t paddr; void __iomem *vaddr; unsigned int size; }; /* get physical memory information of a drm framebuffer. */ struct imx_drm_buf_entry *imx_drm_fb_get_buf(struct drm_framebuffer *fb); struct imx_drm_encoder; int imx_drm_add_encoder(struct drm_encoder *encoder, struct imx_drm_encoder **new_enc, struct module *owner); int imx_drm_remove_encoder(struct imx_drm_encoder *); struct imx_drm_connector; int imx_drm_add_connector(struct drm_connector *connector, struct imx_drm_connector **new_con, struct module *owner); int imx_drm_remove_connector(struct imx_drm_connector *); void imx_drm_mode_config_init(struct drm_device *drm); #define to_imx_drm_gem_obj(x) container_of(x,\ struct imx_drm_gem_obj, base) struct imx_drm_gem_obj { struct drm_gem_object base; struct imx_drm_buf_entry *entry; }; /* unmap a buffer from user space. */ int imx_drm_gem_munmap_ioctl(struct drm_device *drm, void *data, struct drm_file *file_priv); /* initialize gem object. */ int imx_drm_gem_init_object(struct drm_gem_object *obj); /* free gem object. */ void imx_drm_gem_free_object(struct drm_gem_object *gem_obj); /* create memory region for drm framebuffer. */ int imx_drm_gem_dumb_create(struct drm_file *file_priv, struct drm_device *drm, struct drm_mode_create_dumb *args); /* map memory region for drm framebuffer to user space. */ int imx_drm_gem_dumb_map_offset(struct drm_file *file_priv, struct drm_device *drm, uint32_t handle, uint64_t *offset); /* page fault handler and mmap fault address(virtual) to physical memory. */ int imx_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); /* set vm_flags and we can change the vm attribute to other one at here. */ int imx_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma); /* * destroy memory region allocated. * - a gem handle and physical memory region pointed by a gem object * would be released by drm_gem_handle_delete(). */ int imx_drm_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *drm, unsigned int handle); /* allocate physical memory. */ struct imx_drm_buf_entry *imx_drm_buf_create(struct drm_device *drm, unsigned int size); /* remove allocated physical memory. */ void imx_drm_buf_destroy(struct drm_device *drm, struct imx_drm_buf_entry *entry); struct drm_device *imx_drm_device_get(void); void imx_drm_device_put(void); #endif /* _IMX_DRM_H_ */ -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2012-05-22 14:06 ` Lars-Peter Clausen 2012-05-23 8:12 ` Re: Sascha Hauer @ 2012-05-24 6:31 ` Sascha Hauer 1 sibling, 0 replies; 42+ messages in thread From: Sascha Hauer @ 2012-05-24 6:31 UTC (permalink / raw) To: Lars-Peter Clausen; +Cc: linux-arm-kernel, dri-devel On Tue, May 22, 2012 at 04:06:41PM +0200, Lars-Peter Clausen wrote: > On 05/18/2012 02:27 PM, Sascha Hauer wrote: > > Hi All, > > > > The following adds a drm/kms driver for the Freescale i.MX LCDC > > controller. Most notable change to the last SDRM based version is that > > the SDRM layer has been removed and the driver now is purely i.MX > > specific. I hope that this is more acceptable now. > > > > Another change is that the probe is now devicetree based. For now I > > took the easy way out and only put an edid blob into the devicetree. > > I haven't documented the binding yet, I would add that when the rest > > is considered ok. > > > > Comments very welcome. > > > > Hi, > > I really liked the sdrm layer. At least some bits of it. I've been working > on a "simple" DRM driver as well. The hardware has no fancy acceleration > features, just a simple buffer and some scanout logic. I'm basically using > the same gem buffer structure and the buffer is also allocated using > dma_alloc_writecombine, which means we can probably share all of the GEM > handling code and probably also most of the fbdev code. I also started with > the Exynos GEM code as a template, but reworked it later to be more like the > UDL code, which made it a bit more compact. I think it would be a good idea > to put at least the GEM handling in some common code as I expect that we'll > see more similar "simple" DRM drivers pop up. Ok, I'll try to put the GEM stuff into helper functions. Would you care to review/test it? I have something else to do right now but I hope I'll be there next week. Sascha -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | ^ permalink raw reply [flat|nested] 42+ messages in thread
* (unknown), @ 2013-08-13 9:56 Christian König 2013-08-13 14:47 ` Alex Deucher 0 siblings, 1 reply; 42+ messages in thread From: Christian König @ 2013-08-13 9:56 UTC (permalink / raw) To: alexdeucher; +Cc: dri-devel Hey Alex, here are my patches for reworking the ring function pointers and separating out the UVD and DMA rings. Everything is rebased on your drm-next-3.12-wip branch, please review and add them to your branch. Thanks, Christian. ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2013-08-13 9:56 (unknown), Christian König @ 2013-08-13 14:47 ` Alex Deucher 0 siblings, 0 replies; 42+ messages in thread From: Alex Deucher @ 2013-08-13 14:47 UTC (permalink / raw) To: Christian König; +Cc: dri-devel On Tue, Aug 13, 2013 at 5:56 AM, Christian König <deathsimple@vodafone.de> wrote: > Hey Alex, > > here are my patches for reworking the ring function pointers and separating out the UVD and DMA rings. > > Everything is rebased on your drm-next-3.12-wip branch, please review and add them to your branch. Patches look good to me. I've added them to my 3.12 tree. Alex ^ permalink raw reply [flat|nested] 42+ messages in thread
* (unknown), @ 2014-08-24 13:14 Christian König 2014-08-24 13:34 ` Mike Lothian 0 siblings, 1 reply; 42+ messages in thread From: Christian König @ 2014-08-24 13:14 UTC (permalink / raw) To: dri-devel Hello everyone, the following patches add UVD support for older ASICs (RV6xx, RS[78]80, RV7[79]0). For everybody wanting to test it I've also uploaded a branch to FDO: http://cgit.freedesktop.org/~deathsimple/linux/log/?h=uvd-r600-release Additionally to the patches you need UVD firmware as well, which can be found at the usual location: http://people.freedesktop.org/~agd5f/radeon_ucode/ A small Mesa patch is needed as well, cause the older hardware doesn't support field based output of video frames. So unfortunately VDPAU/OpenGL interop won't work either. We can only provide best effort support for those older ASICs, but at least on my RS[78]80 based laptop it seems to work perfectly fine. Happy testing, Christian. ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2014-08-24 13:14 (unknown), Christian König @ 2014-08-24 13:34 ` Mike Lothian 2014-08-25 9:10 ` Re: Christian König 0 siblings, 1 reply; 42+ messages in thread From: Mike Lothian @ 2014-08-24 13:34 UTC (permalink / raw) To: Christian König; +Cc: dri-devel [-- Attachment #1.1: Type: text/plain, Size: 1070 bytes --] Thanks for this Good work On 24 Aug 2014 14:15, "Christian König" <deathsimple@vodafone.de> wrote: > Hello everyone, > > the following patches add UVD support for older ASICs (RV6xx, RS[78]80, > RV7[79]0). For everybody wanting to test it I've also uploaded a branch to > FDO: > http://cgit.freedesktop.org/~deathsimple/linux/log/?h=uvd-r600-release > > Additionally to the patches you need UVD firmware as well, which can be > found at the usual location: > http://people.freedesktop.org/~agd5f/radeon_ucode/ > > A small Mesa patch is needed as well, cause the older hardware doesn't > support field based output of video frames. So unfortunately VDPAU/OpenGL > interop won't work either. > > We can only provide best effort support for those older ASICs, but at > least on my RS[78]80 based laptop it seems to work perfectly fine. > > Happy testing, > Christian. > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel > [-- Attachment #1.2: Type: text/html, Size: 1682 bytes --] [-- Attachment #2: Type: text/plain, Size: 159 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2014-08-24 13:34 ` Mike Lothian @ 2014-08-25 9:10 ` Christian König 2014-09-07 13:24 ` Re: Markus Trippelsdorf 0 siblings, 1 reply; 42+ messages in thread From: Christian König @ 2014-08-25 9:10 UTC (permalink / raw) To: Mike Lothian; +Cc: dri-devel [-- Attachment #1.1: Type: text/plain, Size: 1550 bytes --] Let me know if it works for you, cause we don't really have any hardware any more to test it. Christian. Am 24.08.2014 um 15:34 schrieb Mike Lothian: > > Thanks for this > > Good work > > On 24 Aug 2014 14:15, "Christian König" <deathsimple@vodafone.de > <mailto:deathsimple@vodafone.de>> wrote: > > Hello everyone, > > the following patches add UVD support for older ASICs (RV6xx, > RS[78]80, RV7[79]0). For everybody wanting to test it I've also > uploaded a branch to FDO: > http://cgit.freedesktop.org/~deathsimple/linux/log/?h=uvd-r600-release > <http://cgit.freedesktop.org/%7Edeathsimple/linux/log/?h=uvd-r600-release> > > Additionally to the patches you need UVD firmware as well, which > can be found at the usual location: > http://people.freedesktop.org/~agd5f/radeon_ucode/ > <http://people.freedesktop.org/%7Eagd5f/radeon_ucode/> > > A small Mesa patch is needed as well, cause the older hardware > doesn't support field based output of video frames. So > unfortunately VDPAU/OpenGL interop won't work either. > > We can only provide best effort support for those older ASICs, but > at least on my RS[78]80 based laptop it seems to work perfectly fine. > > Happy testing, > Christian. > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > <mailto:dri-devel@lists.freedesktop.org> > http://lists.freedesktop.org/mailman/listinfo/dri-devel > [-- Attachment #1.2: Type: text/html, Size: 2761 bytes --] [-- Attachment #2: Type: text/plain, Size: 159 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2014-08-25 9:10 ` Re: Christian König @ 2014-09-07 13:24 ` Markus Trippelsdorf 2014-09-08 3:47 ` Re: Alex Deucher 0 siblings, 1 reply; 42+ messages in thread From: Markus Trippelsdorf @ 2014-09-07 13:24 UTC (permalink / raw) To: Christian König; +Cc: dri-devel On 2014.08.25 at 11:10 +0200, Christian König wrote: > Let me know if it works for you, cause we don't really have any hardware > any more to test it. I've tested your patch series today (using drm-next-3.18 from ~agd5f/linux) on a RS780D/Radeon HD 3300 system with a couple of H264 videos. While it sometimes works as expected, it stalled the GPU far too often to be usable. The stalls are not recoverable and the machine ends up with a black sreen, but still accepts SysRq keyboard inputs. Here are some logs: vdpauinfo: display: :0 screen: 0 API version: 1 Information string: G3DVL VDPAU Driver Shared Library version 1.0 Video surface: name width height types ------------------------------------------- 420 8192 8192 NV12 YV12 422 8192 8192 UYVY YUYV 444 8192 8192 Y8U8V8A8 V8U8Y8A8 Decoder capabilities: name level macbs width height ------------------------------------------- MPEG1 0 9216 2048 1152 MPEG2_SIMPLE 3 9216 2048 1152 MPEG2_MAIN 3 9216 2048 1152 H264_BASELINE 41 9216 2048 1152 H264_MAIN 41 9216 2048 1152 H264_HIGH 41 9216 2048 1152 VC1_ADVANCED 4 9216 2048 1152 Output surface: name width height nat types ---------------------------------------------------- B8G8R8A8 8192 8192 y NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 R8G8B8A8 8192 8192 y NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 R10G10B10A2 8192 8192 y NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 B10G10R10A2 8192 8192 y NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 Bitmap surface: name width height ------------------------------ B8G8R8A8 8192 8192 R8G8B8A8 8192 8192 R10G10B10A2 8192 8192 B10G10R10A2 8192 8192 A8 8192 8192 Video mixer: feature name sup ------------------------------------ DEINTERLACE_TEMPORAL y DEINTERLACE_TEMPORAL_SPATIAL - INVERSE_TELECINE - NOISE_REDUCTION y SHARPNESS y LUMA_KEY - HIGH QUALITY SCALING - L1 - HIGH QUALITY SCALING - L2 - HIGH QUALITY SCALING - L3 - HIGH QUALITY SCALING - L4 - HIGH QUALITY SCALING - L5 - HIGH QUALITY SCALING - L6 - HIGH QUALITY SCALING - L7 - HIGH QUALITY SCALING - L8 - HIGH QUALITY SCALING - L9 - parameter name sup min max ----------------------------------------------------- VIDEO_SURFACE_WIDTH y 48 2048 VIDEO_SURFACE_HEIGHT y 48 1152 CHROMA_TYPE y LAYERS y 0 4 attribute name sup min max ----------------------------------------------------- BACKGROUND_COLOR y CSC_MATRIX y NOISE_REDUCTION_LEVEL y 0.00 1.00 SHARPNESS_LEVEL y -1.00 1.00 LUMA_KEY_MIN_LUMA y LUMA_KEY_MAX_LUMA y Sep 7 14:03:45 x4 kernel: [drm] Initialized drm 1.1.0 20060810 Sep 7 14:03:45 x4 kernel: [drm] radeon kernel modesetting enabled. Sep 7 14:03:45 x4 kernel: [drm] initializing kernel modesetting (RS780 0x1002:0x9614 0x1043:0x834D). Sep 7 14:03:45 x4 kernel: [drm] register mmio base: 0xFBEE0000 Sep 7 14:03:45 x4 kernel: [drm] register mmio size: 65536 Sep 7 14:03:45 x4 kernel: ATOM BIOS: 113 Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: VRAM: 128M 0x00000000C0000000 - 0x00000000C7FFFFFF (128M used) Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: GTT: 512M 0x00000000A0000000 - 0x00000000BFFFFFFF Sep 7 14:03:45 x4 kernel: [drm] Detected VRAM RAM=128M, BAR=128M Sep 7 14:03:45 x4 kernel: [drm] RAM width 32bits DDR Sep 7 14:03:45 x4 kernel: [TTM] Zone kernel: Available graphics memory: 4083350 kiB Sep 7 14:03:45 x4 kernel: [TTM] Zone dma32: Available graphics memory: 2097152 kiB Sep 7 14:03:45 x4 kernel: [TTM] Initializing pool allocator Sep 7 14:03:45 x4 kernel: [TTM] Initializing DMA pool allocator Sep 7 14:03:45 x4 kernel: [drm] radeon: 128M of VRAM memory ready Sep 7 14:03:45 x4 kernel: [drm] radeon: 512M of GTT memory ready. Sep 7 14:03:45 x4 kernel: [drm] Loading RS780 Microcode Sep 7 14:03:45 x4 kernel: == power state 0 == Sep 7 14:03:45 x4 kernel: ui class: none Sep 7 14:03:45 x4 kernel: internal class: boot Sep 7 14:03:45 x4 kernel: caps: video Sep 7 14:03:45 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 Sep 7 14:03:45 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 Sep 7 14:03:45 x4 kernel: status: c r b Sep 7 14:03:45 x4 kernel: == power state 1 == Sep 7 14:03:45 x4 kernel: ui class: performance Sep 7 14:03:45 x4 kernel: internal class: none Sep 7 14:03:45 x4 kernel: caps: video Sep 7 14:03:45 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:03:45 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 Sep 7 14:03:45 x4 kernel: status: Sep 7 14:03:45 x4 kernel: == power state 2 == Sep 7 14:03:45 x4 kernel: ui class: none Sep 7 14:03:45 x4 kernel: internal class: uvd Sep 7 14:03:45 x4 kernel: caps: video Sep 7 14:03:45 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:03:45 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:03:45 x4 kernel: status: Sep 7 14:03:45 x4 kernel: [drm] radeon: dpm initialized Sep 7 14:03:45 x4 kernel: [drm] GART: num cpu pages 131072, num gpu pages 131072 Sep 7 14:03:45 x4 kernel: [drm] PCIE GART of 512M enabled (table at 0x00000000C0258000). Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: WB enabled Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: fence driver on ring 0 use gpu addr 0x00000000a0000c00 and cpu addr 0xffff8800db8dcc00 Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: fence driver on ring 5 use gpu addr 0x00000000c0056038 and cpu addr 0xffffc90000116038 Sep 7 14:03:45 x4 kernel: [drm] Supports vblank timestamp caching Rev 2 (21.10.2013). Sep 7 14:03:45 x4 kernel: [drm] Driver supports precise vblank timestamp query. Sep 7 14:03:45 x4 kernel: [drm] radeon: irq initialized. Sep 7 14:03:45 x4 kernel: [drm] ring test on 0 succeeded in 1 usecs Sep 7 14:03:45 x4 kernel: [drm] ring test on 5 succeeded in 1 usecs Sep 7 14:03:45 x4 kernel: [drm] UVD initialized successfully. Sep 7 14:03:45 x4 kernel: [drm] ib test on ring 0 succeeded in 0 usecs Sep 7 14:03:45 x4 kernel: [drm] ib test on ring 5 succeeded Sep 7 14:03:45 x4 kernel: [drm] Radeon Display Connectors Sep 7 14:03:45 x4 kernel: [drm] Connector 0: Sep 7 14:03:45 x4 kernel: [drm] VGA-1 Sep 7 14:03:45 x4 kernel: [drm] DDC: 0x7e40 0x7e40 0x7e44 0x7e44 0x7e48 0x7e48 0x7e4c 0x7e4c Sep 7 14:03:45 x4 kernel: [drm] Encoders: Sep 7 14:03:45 x4 kernel: [drm] CRT1: INTERNAL_KLDSCP_DAC1 Sep 7 14:03:45 x4 kernel: [drm] Connector 1: Sep 7 14:03:45 x4 kernel: [drm] DVI-D-1 Sep 7 14:03:45 x4 kernel: [drm] HPD3 Sep 7 14:03:45 x4 kernel: [drm] DDC: 0x7e50 0x7e50 0x7e54 0x7e54 0x7e58 0x7e58 0x7e5c 0x7e5c Sep 7 14:03:45 x4 kernel: [drm] Encoders: Sep 7 14:03:45 x4 kernel: [drm] DFP3: INTERNAL_KLDSCP_LVTMA Sep 7 14:03:45 x4 kernel: switching from power state: Sep 7 14:03:45 x4 kernel: ui class: none Sep 7 14:03:45 x4 kernel: internal class: boot Sep 7 14:03:45 x4 kernel: caps: video Sep 7 14:03:45 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 Sep 7 14:03:45 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 Sep 7 14:03:45 x4 kernel: status: c b Sep 7 14:03:45 x4 kernel: switching to power state: Sep 7 14:03:45 x4 kernel: ui class: performance Sep 7 14:03:45 x4 kernel: internal class: none Sep 7 14:03:45 x4 kernel: caps: video Sep 7 14:03:45 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:03:45 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 Sep 7 14:03:45 x4 kernel: status: r Sep 7 14:03:45 x4 kernel: [drm] fb mappable at 0xF0359000 Sep 7 14:03:45 x4 kernel: [drm] vram apper at 0xF0000000 Sep 7 14:03:45 x4 kernel: [drm] size 7299072 Sep 7 14:03:45 x4 kernel: [drm] fb depth is 24 Sep 7 14:03:45 x4 kernel: [drm] pitch is 6912 Sep 7 14:03:45 x4 kernel: fbcon: radeondrmfb (fb0) is primary device Sep 7 14:03:45 x4 kernel: Console: switching to colour frame buffer device 131x105 Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: fb0: radeondrmfb frame buffer device Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: registered panic notifier Sep 7 14:03:45 x4 kernel: tsc: Refined TSC clocksource calibration: 3210.826 MHz Sep 7 14:03:45 x4 kernel: [drm] Initialized radeon 2.40.0 20080528 for 0000:01:05.0 on minor 0 ... Sep 7 14:20:37 x4 kernel: switching to power state: Sep 7 14:20:37 x4 kernel: ui class: none Sep 7 14:20:37 x4 kernel: internal class: uvd Sep 7 14:20:37 x4 kernel: caps: video Sep 7 14:20:37 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:20:37 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:20:37 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:20:37 x4 kernel: status: r Sep 7 14:20:54 x4 kernel: switching from power state: Sep 7 14:20:54 x4 kernel: ui class: none Sep 7 14:20:54 x4 kernel: internal class: uvd Sep 7 14:20:54 x4 kernel: caps: video Sep 7 14:20:54 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:20:54 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:20:54 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:20:54 x4 kernel: status: c Sep 7 14:20:54 x4 kernel: switching to power state: Sep 7 14:20:54 x4 kernel: ui class: performance Sep 7 14:20:54 x4 kernel: internal class: none Sep 7 14:20:54 x4 kernel: caps: video Sep 7 14:20:54 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:20:54 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:20:54 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 Sep 7 14:20:54 x4 kernel: status: r Sep 7 14:21:02 x4 kernel: switching from power state: Sep 7 14:21:02 x4 kernel: ui class: performance Sep 7 14:21:02 x4 kernel: internal class: none Sep 7 14:21:02 x4 kernel: caps: video Sep 7 14:21:02 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:21:02 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:21:02 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 Sep 7 14:21:02 x4 kernel: status: c Sep 7 14:21:02 x4 kernel: switching to power state: Sep 7 14:21:02 x4 kernel: ui class: none Sep 7 14:21:02 x4 kernel: internal class: uvd Sep 7 14:21:02 x4 kernel: caps: video Sep 7 14:21:02 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:21:02 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:21:02 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:21:02 x4 kernel: status: r Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10106msec Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000072ac last fence id 0x00000000000072b4 on ring 0) Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: Saved 377 dwords of commands on ring 0. Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: GPU softreset: 0x00000099 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA00034AF Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20044040 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000004 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000002 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00005087 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80098645 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008020_GRBM_SOFT_RESET=0x00007FEF Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: SRBM_SOFT_RESET=0x00008100 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA0003030 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20048040 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000000 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000000 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00000000 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80100000 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: GPU reset succeeded, trying to resume Sep 7 14:21:13 x4 kernel: [drm] PCIE GART of 512M enabled (table at 0x00000000C0258000). Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: WB enabled Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: fence driver on ring 0 use gpu addr 0x00000000a0000c00 and cpu addr 0xffff8800db8dcc00 Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: fence driver on ring 5 use gpu addr 0x00000000c0056038 and cpu addr 0xffffc90000116038 Sep 7 14:21:13 x4 kernel: [drm] ring test on 0 succeeded in 1 usecs Sep 7 14:21:13 x4 kernel: [drm] ring test on 5 succeeded in 1 usecs Sep 7 14:21:13 x4 kernel: [drm] UVD initialized successfully. Sep 7 14:21:13 x4 kernel: switching from power state: Sep 7 14:21:13 x4 kernel: ui class: none Sep 7 14:21:13 x4 kernel: internal class: boot Sep 7 14:21:13 x4 kernel: caps: video Sep 7 14:21:13 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:21:13 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 Sep 7 14:21:13 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 Sep 7 14:21:13 x4 kernel: status: c b Sep 7 14:21:13 x4 kernel: switching to power state: Sep 7 14:21:13 x4 kernel: ui class: none Sep 7 14:21:13 x4 kernel: internal class: uvd Sep 7 14:21:13 x4 kernel: caps: video Sep 7 14:21:13 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:21:13 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:21:13 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:21:13 x4 kernel: status: r Sep 7 14:21:20 x4 kernel: SysRq : Emergency Sync (new boot) Sep 7 14:44:49 x4 kernel: switching from power state: Sep 7 14:44:49 x4 kernel: ui class: performance Sep 7 14:44:49 x4 kernel: internal class: none Sep 7 14:44:49 x4 kernel: caps: video Sep 7 14:44:49 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:44:49 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:44:49 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 Sep 7 14:44:49 x4 kernel: status: c Sep 7 14:44:49 x4 kernel: switching to power state: Sep 7 14:44:49 x4 kernel: ui class: none Sep 7 14:44:49 x4 kernel: internal class: uvd Sep 7 14:44:49 x4 kernel: caps: video Sep 7 14:44:49 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:44:49 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:44:49 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:44:49 x4 kernel: status: r Sep 7 14:44:59 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 10000msec Sep 7 14:44:59 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000eac last fence id 0x0000000000000eaf on ring 5) Sep 7 14:44:59 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10466msec Sep 7 14:44:59 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000064ff last fence id 0x0000000000006504 on ring 0) Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 10500msec Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000eac last fence id 0x0000000000000eaf on ring 5) Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10966msec Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000064ff last fence id 0x0000000000006504 on ring 0) Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 11000msec ... Sep 7 14:45:17 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000eac last fence id 0x0000000000000eaf on ring 5) Sep 7 14:45:17 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 28466msec Sep 7 14:45:17 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000064ff last fence id 0x0000000000006504 on ring 0) Sep 7 14:45:18 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 28500msec Sep 7 14:45:18 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000eac last fence id 0x0000000000000eaf on ring 5) Sep 7 14:45:18 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 28966msec Sep 7 14:45:18 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000064ff last fence id 0x0000000000006504 on ring 0) Sep 7 14:45:18 x4 kernel: SysRq : Emergency Sync (new boot) Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 10000msec Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10000msec Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000001ed last fence id 0x00000000000001f6 on ring 0) Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x000000000000000b last fence id 0x000000000000000f on ring 5) Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: Saved 409 dwords of commands on ring 0. Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: GPU softreset: 0x00000099 Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA00034E0 Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20045040 Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x01000004 Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00200002 Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00005087 Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x808D8645 Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008020_GRBM_SOFT_RESET=0x00007FEF Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: SRBM_SOFT_RESET=0x00008100 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA0003030 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20048040 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000000 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000000 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00000000 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80100000 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: GPU reset succeeded, trying to resume Sep 7 14:48:15 x4 kernel: [drm] PCIE GART of 512M enabled (table at 0x00000000C0258000). Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: WB enabled Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: fence driver on ring 0 use gpu addr 0x00000000a0000c00 and cpu addr 0xffff8800db8dcc00 Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: fence driver on ring 5 use gpu addr 0x00000000c0056038 and cpu addr 0xffffc90000116038 Sep 7 14:48:15 x4 kernel: [drm] ring test on 0 succeeded in 1 usecs Sep 7 14:48:15 x4 kernel: [drm] ring test on 5 succeeded in 1 usecs Sep 7 14:48:15 x4 kernel: [drm] UVD initialized successfully. Sep 7 14:48:15 x4 kernel: switching from power state: Sep 7 14:48:15 x4 kernel: ui class: none Sep 7 14:48:15 x4 kernel: internal class: boot Sep 7 14:48:15 x4 kernel: caps: video Sep 7 14:48:15 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:48:15 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 Sep 7 14:48:15 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 Sep 7 14:48:15 x4 kernel: status: c b Sep 7 14:48:15 x4 kernel: switching to power state: Sep 7 14:48:15 x4 kernel: ui class: none Sep 7 14:48:15 x4 kernel: internal class: uvd Sep 7 14:48:15 x4 kernel: caps: video Sep 7 14:48:15 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:48:15 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:48:15 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:48:15 x4 kernel: status: r Sep 7 14:48:15 x4 kernel: SysRq : Emergency Sync (new boot) Sep 7 14:53:20 x4 kernel: switching to power state: Sep 7 14:53:20 x4 kernel: ui class: none Sep 7 14:53:20 x4 kernel: internal class: uvd Sep 7 14:53:20 x4 kernel: caps: video Sep 7 14:53:20 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:53:20 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:53:20 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:53:20 x4 kernel: status: r Sep 7 14:53:30 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10050msec Sep 7 14:53:30 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000596 last fence id 0x00000000000005a3 on ring 0) Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: Saved 601 dwords of commands on ring 0. Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: GPU softreset: 0x00000088 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA00030B0 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20045040 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000004 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000002 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00005087 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80098645 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008020_GRBM_SOFT_RESET=0x00004001 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: SRBM_SOFT_RESET=0x00008100 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA0003030 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20048040 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000000 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000000 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00000000 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80100000 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: GPU reset succeeded, trying to resume Sep 7 14:53:31 x4 kernel: [drm] PCIE GART of 512M enabled (table at 0x00000000C0258000). Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: WB enabled Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: fence driver on ring 0 use gpu addr 0x00000000a0000c00 and cpu addr 0xffff8800db8dcc00 Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: fence driver on ring 5 use gpu addr 0x00000000c0056038 and cpu addr 0xffffc90000116038 Sep 7 14:53:31 x4 kernel: [drm] ring test on 0 succeeded in 1 usecs Sep 7 14:53:31 x4 kernel: [drm] ring test on 5 succeeded in 1 usecs Sep 7 14:53:31 x4 kernel: [drm] UVD initialized successfully. Sep 7 14:53:31 x4 kernel: switching from power state: Sep 7 14:53:31 x4 kernel: ui class: none Sep 7 14:53:31 x4 kernel: internal class: boot Sep 7 14:53:31 x4 kernel: caps: video Sep 7 14:53:31 x4 kernel: uvd vclk: 0 dclk: 0 Sep 7 14:53:31 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 Sep 7 14:53:31 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 Sep 7 14:53:31 x4 kernel: status: c b Sep 7 14:53:31 x4 kernel: switching to power state: Sep 7 14:53:31 x4 kernel: ui class: none Sep 7 14:53:31 x4 kernel: internal class: uvd Sep 7 14:53:31 x4 kernel: caps: video Sep 7 14:53:31 x4 kernel: uvd vclk: 53300 dclk: 40000 Sep 7 14:53:31 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 Sep 7 14:53:31 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 Sep 7 14:53:31 x4 kernel: status: r Sep 7 14:53:39 x4 kernel: SysRq : Emergency Sync -- Markus ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2014-09-07 13:24 ` Re: Markus Trippelsdorf @ 2014-09-08 3:47 ` Alex Deucher 2014-09-08 7:13 ` Re: Markus Trippelsdorf 0 siblings, 1 reply; 42+ messages in thread From: Alex Deucher @ 2014-09-08 3:47 UTC (permalink / raw) To: Markus Trippelsdorf; +Cc: Maling list - DRI developers On Sun, Sep 7, 2014 at 9:24 AM, Markus Trippelsdorf <markus@trippelsdorf.de> wrote: > On 2014.08.25 at 11:10 +0200, Christian König wrote: >> Let me know if it works for you, cause we don't really have any hardware >> any more to test it. > > I've tested your patch series today (using drm-next-3.18 from > ~agd5f/linux) on a RS780D/Radeon HD 3300 system with a couple of H264 > videos. While it sometimes works as expected, it stalled the GPU far too > often to be usable. The stalls are not recoverable and the machine ends > up with a black sreen, but still accepts SysRq keyboard inputs. Does it work any better if dpm is disabled? Alex > > Here are some logs: > > vdpauinfo: > display: :0 screen: 0 > API version: 1 > Information string: G3DVL VDPAU Driver Shared Library version 1.0 > > Video surface: > > name width height types > ------------------------------------------- > 420 8192 8192 NV12 YV12 > 422 8192 8192 UYVY YUYV > 444 8192 8192 Y8U8V8A8 V8U8Y8A8 > > Decoder capabilities: > > name level macbs width height > ------------------------------------------- > MPEG1 0 9216 2048 1152 > MPEG2_SIMPLE 3 9216 2048 1152 > MPEG2_MAIN 3 9216 2048 1152 > H264_BASELINE 41 9216 2048 1152 > H264_MAIN 41 9216 2048 1152 > H264_HIGH 41 9216 2048 1152 > VC1_ADVANCED 4 9216 2048 1152 > > Output surface: > > name width height nat types > ---------------------------------------------------- > B8G8R8A8 8192 8192 y NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 > R8G8B8A8 8192 8192 y NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 > R10G10B10A2 8192 8192 y NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 > B10G10R10A2 8192 8192 y NV12 YV12 UYVY YUYV Y8U8V8A8 V8U8Y8A8 > > Bitmap surface: > > name width height > ------------------------------ > B8G8R8A8 8192 8192 > R8G8B8A8 8192 8192 > R10G10B10A2 8192 8192 > B10G10R10A2 8192 8192 > A8 8192 8192 > > Video mixer: > > feature name sup > ------------------------------------ > DEINTERLACE_TEMPORAL y > DEINTERLACE_TEMPORAL_SPATIAL - > INVERSE_TELECINE - > NOISE_REDUCTION y > SHARPNESS y > LUMA_KEY - > HIGH QUALITY SCALING - L1 - > HIGH QUALITY SCALING - L2 - > HIGH QUALITY SCALING - L3 - > HIGH QUALITY SCALING - L4 - > HIGH QUALITY SCALING - L5 - > HIGH QUALITY SCALING - L6 - > HIGH QUALITY SCALING - L7 - > HIGH QUALITY SCALING - L8 - > HIGH QUALITY SCALING - L9 - > > parameter name sup min max > ----------------------------------------------------- > VIDEO_SURFACE_WIDTH y 48 2048 > VIDEO_SURFACE_HEIGHT y 48 1152 > CHROMA_TYPE y > LAYERS y 0 4 > > attribute name sup min max > ----------------------------------------------------- > BACKGROUND_COLOR y > CSC_MATRIX y > NOISE_REDUCTION_LEVEL y 0.00 1.00 > SHARPNESS_LEVEL y -1.00 1.00 > LUMA_KEY_MIN_LUMA y > LUMA_KEY_MAX_LUMA y > > > Sep 7 14:03:45 x4 kernel: [drm] Initialized drm 1.1.0 20060810 > Sep 7 14:03:45 x4 kernel: [drm] radeon kernel modesetting enabled. > Sep 7 14:03:45 x4 kernel: [drm] initializing kernel modesetting (RS780 0x1002:0x9614 0x1043:0x834D). > Sep 7 14:03:45 x4 kernel: [drm] register mmio base: 0xFBEE0000 > Sep 7 14:03:45 x4 kernel: [drm] register mmio size: 65536 > Sep 7 14:03:45 x4 kernel: ATOM BIOS: 113 > Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: VRAM: 128M 0x00000000C0000000 - 0x00000000C7FFFFFF (128M used) > Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: GTT: 512M 0x00000000A0000000 - 0x00000000BFFFFFFF > Sep 7 14:03:45 x4 kernel: [drm] Detected VRAM RAM=128M, BAR=128M > Sep 7 14:03:45 x4 kernel: [drm] RAM width 32bits DDR > Sep 7 14:03:45 x4 kernel: [TTM] Zone kernel: Available graphics memory: 4083350 kiB > Sep 7 14:03:45 x4 kernel: [TTM] Zone dma32: Available graphics memory: 2097152 kiB > Sep 7 14:03:45 x4 kernel: [TTM] Initializing pool allocator > Sep 7 14:03:45 x4 kernel: [TTM] Initializing DMA pool allocator > Sep 7 14:03:45 x4 kernel: [drm] radeon: 128M of VRAM memory ready > Sep 7 14:03:45 x4 kernel: [drm] radeon: 512M of GTT memory ready. > Sep 7 14:03:45 x4 kernel: [drm] Loading RS780 Microcode > Sep 7 14:03:45 x4 kernel: == power state 0 == > Sep 7 14:03:45 x4 kernel: ui class: none > Sep 7 14:03:45 x4 kernel: internal class: boot > Sep 7 14:03:45 x4 kernel: caps: video > Sep 7 14:03:45 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 > Sep 7 14:03:45 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 > Sep 7 14:03:45 x4 kernel: status: c r b > Sep 7 14:03:45 x4 kernel: == power state 1 == > Sep 7 14:03:45 x4 kernel: ui class: performance > Sep 7 14:03:45 x4 kernel: internal class: none > Sep 7 14:03:45 x4 kernel: caps: video > Sep 7 14:03:45 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:03:45 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 > Sep 7 14:03:45 x4 kernel: status: > Sep 7 14:03:45 x4 kernel: == power state 2 == > Sep 7 14:03:45 x4 kernel: ui class: none > Sep 7 14:03:45 x4 kernel: internal class: uvd > Sep 7 14:03:45 x4 kernel: caps: video > Sep 7 14:03:45 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:03:45 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:03:45 x4 kernel: status: > Sep 7 14:03:45 x4 kernel: [drm] radeon: dpm initialized > Sep 7 14:03:45 x4 kernel: [drm] GART: num cpu pages 131072, num gpu pages 131072 > Sep 7 14:03:45 x4 kernel: [drm] PCIE GART of 512M enabled (table at 0x00000000C0258000). > Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: WB enabled > Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: fence driver on ring 0 use gpu addr 0x00000000a0000c00 and cpu addr 0xffff8800db8dcc00 > Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: fence driver on ring 5 use gpu addr 0x00000000c0056038 and cpu addr 0xffffc90000116038 > Sep 7 14:03:45 x4 kernel: [drm] Supports vblank timestamp caching Rev 2 (21.10.2013). > Sep 7 14:03:45 x4 kernel: [drm] Driver supports precise vblank timestamp query. > Sep 7 14:03:45 x4 kernel: [drm] radeon: irq initialized. > Sep 7 14:03:45 x4 kernel: [drm] ring test on 0 succeeded in 1 usecs > Sep 7 14:03:45 x4 kernel: [drm] ring test on 5 succeeded in 1 usecs > Sep 7 14:03:45 x4 kernel: [drm] UVD initialized successfully. > Sep 7 14:03:45 x4 kernel: [drm] ib test on ring 0 succeeded in 0 usecs > Sep 7 14:03:45 x4 kernel: [drm] ib test on ring 5 succeeded > Sep 7 14:03:45 x4 kernel: [drm] Radeon Display Connectors > Sep 7 14:03:45 x4 kernel: [drm] Connector 0: > Sep 7 14:03:45 x4 kernel: [drm] VGA-1 > Sep 7 14:03:45 x4 kernel: [drm] DDC: 0x7e40 0x7e40 0x7e44 0x7e44 0x7e48 0x7e48 0x7e4c 0x7e4c > Sep 7 14:03:45 x4 kernel: [drm] Encoders: > Sep 7 14:03:45 x4 kernel: [drm] CRT1: INTERNAL_KLDSCP_DAC1 > Sep 7 14:03:45 x4 kernel: [drm] Connector 1: > Sep 7 14:03:45 x4 kernel: [drm] DVI-D-1 > Sep 7 14:03:45 x4 kernel: [drm] HPD3 > Sep 7 14:03:45 x4 kernel: [drm] DDC: 0x7e50 0x7e50 0x7e54 0x7e54 0x7e58 0x7e58 0x7e5c 0x7e5c > Sep 7 14:03:45 x4 kernel: [drm] Encoders: > Sep 7 14:03:45 x4 kernel: [drm] DFP3: INTERNAL_KLDSCP_LVTMA > Sep 7 14:03:45 x4 kernel: switching from power state: > Sep 7 14:03:45 x4 kernel: ui class: none > Sep 7 14:03:45 x4 kernel: internal class: boot > Sep 7 14:03:45 x4 kernel: caps: video > Sep 7 14:03:45 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 > Sep 7 14:03:45 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 > Sep 7 14:03:45 x4 kernel: status: c b > Sep 7 14:03:45 x4 kernel: switching to power state: > Sep 7 14:03:45 x4 kernel: ui class: performance > Sep 7 14:03:45 x4 kernel: internal class: none > Sep 7 14:03:45 x4 kernel: caps: video > Sep 7 14:03:45 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:03:45 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:03:45 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 > Sep 7 14:03:45 x4 kernel: status: r > Sep 7 14:03:45 x4 kernel: [drm] fb mappable at 0xF0359000 > Sep 7 14:03:45 x4 kernel: [drm] vram apper at 0xF0000000 > Sep 7 14:03:45 x4 kernel: [drm] size 7299072 > Sep 7 14:03:45 x4 kernel: [drm] fb depth is 24 > Sep 7 14:03:45 x4 kernel: [drm] pitch is 6912 > Sep 7 14:03:45 x4 kernel: fbcon: radeondrmfb (fb0) is primary device > Sep 7 14:03:45 x4 kernel: Console: switching to colour frame buffer device 131x105 > Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: fb0: radeondrmfb frame buffer device > Sep 7 14:03:45 x4 kernel: radeon 0000:01:05.0: registered panic notifier > Sep 7 14:03:45 x4 kernel: tsc: Refined TSC clocksource calibration: 3210.826 MHz > Sep 7 14:03:45 x4 kernel: [drm] Initialized radeon 2.40.0 20080528 for 0000:01:05.0 on minor 0 > ... > Sep 7 14:20:37 x4 kernel: switching to power state: > Sep 7 14:20:37 x4 kernel: ui class: none > Sep 7 14:20:37 x4 kernel: internal class: uvd > Sep 7 14:20:37 x4 kernel: caps: video > Sep 7 14:20:37 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:20:37 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:20:37 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:20:37 x4 kernel: status: r > Sep 7 14:20:54 x4 kernel: switching from power state: > Sep 7 14:20:54 x4 kernel: ui class: none > Sep 7 14:20:54 x4 kernel: internal class: uvd > Sep 7 14:20:54 x4 kernel: caps: video > Sep 7 14:20:54 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:20:54 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:20:54 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:20:54 x4 kernel: status: c > Sep 7 14:20:54 x4 kernel: switching to power state: > Sep 7 14:20:54 x4 kernel: ui class: performance > Sep 7 14:20:54 x4 kernel: internal class: none > Sep 7 14:20:54 x4 kernel: caps: video > Sep 7 14:20:54 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:20:54 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:20:54 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 > Sep 7 14:20:54 x4 kernel: status: r > Sep 7 14:21:02 x4 kernel: switching from power state: > Sep 7 14:21:02 x4 kernel: ui class: performance > Sep 7 14:21:02 x4 kernel: internal class: none > Sep 7 14:21:02 x4 kernel: caps: video > Sep 7 14:21:02 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:21:02 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:21:02 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 > Sep 7 14:21:02 x4 kernel: status: c > Sep 7 14:21:02 x4 kernel: switching to power state: > Sep 7 14:21:02 x4 kernel: ui class: none > Sep 7 14:21:02 x4 kernel: internal class: uvd > Sep 7 14:21:02 x4 kernel: caps: video > Sep 7 14:21:02 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:21:02 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:21:02 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:21:02 x4 kernel: status: r > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10106msec > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000072ac last fence id 0x00000000000072b4 on ring 0) > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: Saved 377 dwords of commands on ring 0. > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: GPU softreset: 0x00000099 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA00034AF > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20044040 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000004 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000002 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00005087 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80098645 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008020_GRBM_SOFT_RESET=0x00007FEF > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: SRBM_SOFT_RESET=0x00008100 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA0003030 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20048040 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000000 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000000 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00000000 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80100000 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: GPU reset succeeded, trying to resume > Sep 7 14:21:13 x4 kernel: [drm] PCIE GART of 512M enabled (table at 0x00000000C0258000). > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: WB enabled > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: fence driver on ring 0 use gpu addr 0x00000000a0000c00 and cpu addr 0xffff8800db8dcc00 > Sep 7 14:21:13 x4 kernel: radeon 0000:01:05.0: fence driver on ring 5 use gpu addr 0x00000000c0056038 and cpu addr 0xffffc90000116038 > Sep 7 14:21:13 x4 kernel: [drm] ring test on 0 succeeded in 1 usecs > Sep 7 14:21:13 x4 kernel: [drm] ring test on 5 succeeded in 1 usecs > Sep 7 14:21:13 x4 kernel: [drm] UVD initialized successfully. > Sep 7 14:21:13 x4 kernel: switching from power state: > Sep 7 14:21:13 x4 kernel: ui class: none > Sep 7 14:21:13 x4 kernel: internal class: boot > Sep 7 14:21:13 x4 kernel: caps: video > Sep 7 14:21:13 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:21:13 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 > Sep 7 14:21:13 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 > Sep 7 14:21:13 x4 kernel: status: c b > Sep 7 14:21:13 x4 kernel: switching to power state: > Sep 7 14:21:13 x4 kernel: ui class: none > Sep 7 14:21:13 x4 kernel: internal class: uvd > Sep 7 14:21:13 x4 kernel: caps: video > Sep 7 14:21:13 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:21:13 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:21:13 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:21:13 x4 kernel: status: r > Sep 7 14:21:20 x4 kernel: SysRq : Emergency Sync > (new boot) > Sep 7 14:44:49 x4 kernel: switching from power state: > Sep 7 14:44:49 x4 kernel: ui class: performance > Sep 7 14:44:49 x4 kernel: internal class: none > Sep 7 14:44:49 x4 kernel: caps: video > Sep 7 14:44:49 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:44:49 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:44:49 x4 kernel: power level 1 sclk: 70000 vddc_index: 2 > Sep 7 14:44:49 x4 kernel: status: c > Sep 7 14:44:49 x4 kernel: switching to power state: > Sep 7 14:44:49 x4 kernel: ui class: none > Sep 7 14:44:49 x4 kernel: internal class: uvd > Sep 7 14:44:49 x4 kernel: caps: video > Sep 7 14:44:49 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:44:49 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:44:49 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:44:49 x4 kernel: status: r > Sep 7 14:44:59 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 10000msec > Sep 7 14:44:59 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000eac last fence id 0x0000000000000eaf on ring 5) > Sep 7 14:44:59 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10466msec > Sep 7 14:44:59 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000064ff last fence id 0x0000000000006504 on ring 0) > Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 10500msec > Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000eac last fence id 0x0000000000000eaf on ring 5) > Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10966msec > Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000064ff last fence id 0x0000000000006504 on ring 0) > Sep 7 14:45:00 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 11000msec > ... > Sep 7 14:45:17 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000eac last fence id 0x0000000000000eaf on ring 5) > Sep 7 14:45:17 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 28466msec > Sep 7 14:45:17 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000064ff last fence id 0x0000000000006504 on ring 0) > Sep 7 14:45:18 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 28500msec > Sep 7 14:45:18 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000eac last fence id 0x0000000000000eaf on ring 5) > Sep 7 14:45:18 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 28966msec > Sep 7 14:45:18 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000064ff last fence id 0x0000000000006504 on ring 0) > Sep 7 14:45:18 x4 kernel: SysRq : Emergency Sync > (new boot) > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: ring 5 stalled for more than 10000msec > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10000msec > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x00000000000001ed last fence id 0x00000000000001f6 on ring 0) > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x000000000000000b last fence id 0x000000000000000f on ring 5) > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: Saved 409 dwords of commands on ring 0. > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: GPU softreset: 0x00000099 > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA00034E0 > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20045040 > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x01000004 > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00200002 > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00005087 > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x808D8645 > Sep 7 14:48:14 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008020_GRBM_SOFT_RESET=0x00007FEF > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: SRBM_SOFT_RESET=0x00008100 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA0003030 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20048040 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000000 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000000 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00000000 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80100000 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: GPU reset succeeded, trying to resume > Sep 7 14:48:15 x4 kernel: [drm] PCIE GART of 512M enabled (table at 0x00000000C0258000). > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: WB enabled > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: fence driver on ring 0 use gpu addr 0x00000000a0000c00 and cpu addr 0xffff8800db8dcc00 > Sep 7 14:48:15 x4 kernel: radeon 0000:01:05.0: fence driver on ring 5 use gpu addr 0x00000000c0056038 and cpu addr 0xffffc90000116038 > Sep 7 14:48:15 x4 kernel: [drm] ring test on 0 succeeded in 1 usecs > Sep 7 14:48:15 x4 kernel: [drm] ring test on 5 succeeded in 1 usecs > Sep 7 14:48:15 x4 kernel: [drm] UVD initialized successfully. > Sep 7 14:48:15 x4 kernel: switching from power state: > Sep 7 14:48:15 x4 kernel: ui class: none > Sep 7 14:48:15 x4 kernel: internal class: boot > Sep 7 14:48:15 x4 kernel: caps: video > Sep 7 14:48:15 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:48:15 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 > Sep 7 14:48:15 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 > Sep 7 14:48:15 x4 kernel: status: c b > Sep 7 14:48:15 x4 kernel: switching to power state: > Sep 7 14:48:15 x4 kernel: ui class: none > Sep 7 14:48:15 x4 kernel: internal class: uvd > Sep 7 14:48:15 x4 kernel: caps: video > Sep 7 14:48:15 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:48:15 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:48:15 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:48:15 x4 kernel: status: r > Sep 7 14:48:15 x4 kernel: SysRq : Emergency Sync > (new boot) > Sep 7 14:53:20 x4 kernel: switching to power state: > Sep 7 14:53:20 x4 kernel: ui class: none > Sep 7 14:53:20 x4 kernel: internal class: uvd > Sep 7 14:53:20 x4 kernel: caps: video > Sep 7 14:53:20 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:53:20 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:53:20 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:53:20 x4 kernel: status: r > Sep 7 14:53:30 x4 kernel: radeon 0000:01:05.0: ring 0 stalled for more than 10050msec > Sep 7 14:53:30 x4 kernel: radeon 0000:01:05.0: GPU lockup (current fence id 0x0000000000000596 last fence id 0x00000000000005a3 on ring 0) > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: Saved 601 dwords of commands on ring 0. > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: GPU softreset: 0x00000088 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA00030B0 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20045040 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000004 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000002 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00005087 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80098645 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008020_GRBM_SOFT_RESET=0x00004001 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: SRBM_SOFT_RESET=0x00008100 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008010_GRBM_STATUS = 0xA0003030 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008014_GRBM_STATUS2 = 0x00000003 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_000E50_SRBM_STATUS = 0x20048040 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008674_CP_STALLED_STAT1 = 0x00000000 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008678_CP_STALLED_STAT2 = 0x00000000 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_00867C_CP_BUSY_STAT = 0x00000000 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_008680_CP_STAT = 0x80100000 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: R_00D034_DMA_STATUS_REG = 0x44C83D57 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: GPU reset succeeded, trying to resume > Sep 7 14:53:31 x4 kernel: [drm] PCIE GART of 512M enabled (table at 0x00000000C0258000). > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: WB enabled > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: fence driver on ring 0 use gpu addr 0x00000000a0000c00 and cpu addr 0xffff8800db8dcc00 > Sep 7 14:53:31 x4 kernel: radeon 0000:01:05.0: fence driver on ring 5 use gpu addr 0x00000000c0056038 and cpu addr 0xffffc90000116038 > Sep 7 14:53:31 x4 kernel: [drm] ring test on 0 succeeded in 1 usecs > Sep 7 14:53:31 x4 kernel: [drm] ring test on 5 succeeded in 1 usecs > Sep 7 14:53:31 x4 kernel: [drm] UVD initialized successfully. > Sep 7 14:53:31 x4 kernel: switching from power state: > Sep 7 14:53:31 x4 kernel: ui class: none > Sep 7 14:53:31 x4 kernel: internal class: boot > Sep 7 14:53:31 x4 kernel: caps: video > Sep 7 14:53:31 x4 kernel: uvd vclk: 0 dclk: 0 > Sep 7 14:53:31 x4 kernel: power level 0 sclk: 50000 vddc_index: 2 > Sep 7 14:53:31 x4 kernel: power level 1 sclk: 50000 vddc_index: 2 > Sep 7 14:53:31 x4 kernel: status: c b > Sep 7 14:53:31 x4 kernel: switching to power state: > Sep 7 14:53:31 x4 kernel: ui class: none > Sep 7 14:53:31 x4 kernel: internal class: uvd > Sep 7 14:53:31 x4 kernel: caps: video > Sep 7 14:53:31 x4 kernel: uvd vclk: 53300 dclk: 40000 > Sep 7 14:53:31 x4 kernel: power level 0 sclk: 50000 vddc_index: 1 > Sep 7 14:53:31 x4 kernel: power level 1 sclk: 50000 vddc_index: 1 > Sep 7 14:53:31 x4 kernel: status: r > Sep 7 14:53:39 x4 kernel: SysRq : Emergency Sync > > -- > Markus > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2014-09-08 3:47 ` Re: Alex Deucher @ 2014-09-08 7:13 ` Markus Trippelsdorf 0 siblings, 0 replies; 42+ messages in thread From: Markus Trippelsdorf @ 2014-09-08 7:13 UTC (permalink / raw) To: Alex Deucher; +Cc: Maling list - DRI developers On 2014.09.07 at 23:47 -0400, Alex Deucher wrote: > On Sun, Sep 7, 2014 at 9:24 AM, Markus Trippelsdorf > <markus@trippelsdorf.de> wrote: > > On 2014.08.25 at 11:10 +0200, Christian König wrote: > >> Let me know if it works for you, cause we don't really have any hardware > >> any more to test it. > > > > I've tested your patch series today (using drm-next-3.18 from > > ~agd5f/linux) on a RS780D/Radeon HD 3300 system with a couple of H264 > > videos. While it sometimes works as expected, it stalled the GPU far too > > often to be usable. The stalls are not recoverable and the machine ends > > up with a black sreen, but still accepts SysRq keyboard inputs. > > > Does it work any better if dpm is disabled? Unfortunately no. The symptoms are unchanged. -- Markus ^ permalink raw reply [flat|nested] 42+ messages in thread
* (unknown) @ 2018-03-05 17:06 Meghana Madhyastha 2018-03-05 19:24 ` Noralf Trønnes 0 siblings, 1 reply; 42+ messages in thread From: Meghana Madhyastha @ 2018-03-05 17:06 UTC (permalink / raw) To: Noralf Trønnes, Daniel Vetter, dri-devel linux-spi@vger.kernel.org,Noralf Trønnes <noralf@tronnes.org>,Sean Paul <seanpaul@chromium.org>,kernel@martin.sperl.org Cc: Bcc: Subject: Re: [PATCH v2 0/2] Chunk splitting of spi transfers Reply-To: In-Reply-To: <f6dbf3ca-4c1b-90cc-c4af-8889f7407180@tronnes.org> On Sun, Mar 04, 2018 at 06:38:42PM +0100, Noralf Trønnes wrote: > > Den 02.03.2018 12.11, skrev Meghana Madhyastha: > >On Sun, Feb 25, 2018 at 02:19:10PM +0100, Lukas Wunner wrote: > >>[cc += linux-rpi-kernel@lists.infradead.org] > >> > >>On Sat, Feb 24, 2018 at 06:15:59PM +0000, Meghana Madhyastha wrote: > >>>I've added bcm2835_spi_transfer_one_message in spi-bcm2835. This calls > >>>spi_split_transfers_maxsize to split large chunks for spi dma transfers. > >>>I then removed chunk splitting in the tinydrm spi helper (as now the core > >>>is handling the chunk splitting). However, although the SPI HW should be > >>>able to accomodate up to 65535 bytes for dma transfers, the splitting of > >>>chunks to 65535 bytes results in a dma transfer time out error. However, > >>>when the chunks are split to < 64 bytes it seems to work fine. > >>Hm, that is really odd, how did you test this exactly, what did you > >>use as SPI slave? It contradicts our own experience, we're using > >>Micrel KSZ8851 Ethernet chips as SPI slave on spi0 of a BCM2837 > >>and can send/receive messages via DMA to the tune of several hundred > >>bytes without any issues. In fact, for messages < 96 bytes, DMA is > >>not used at all, so you've probably been using interrupt mode, > >>see the BCM2835_SPI_DMA_MIN_LENGTH macro in spi-bcm2835.c. > >Hi Lukas, > > > >I think you are right. I checked it and its not using the DMA mode which > >is why its working with 64 bytes. > >Noralf, that leaves us back to the > >initial time out problem. I've tried doing the message splitting in > >spi_sync as well as spi_pump_messages. Martin had explained that DMA > >will wait for > >the SPI HW to set the send_more_data line, but the SPI-HW itself will > >stop triggering it when SPI_LEN is 0 causing DMA to wait forever. I > >thought if we split it before itself, the SPI_LEN will not go to zero > >thus preventing this problem, however it didn't work and started > >hanging. So I'm a little uncertain as to how to proceed and debug what > >exactly has caused the time out due to the asynchronous methods. > > I did a quick test and at least this is working: > > int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz, > struct spi_transfer *header, u8 bpw, const void *buf, > size_t len) > { > struct spi_transfer tr = { > .bits_per_word = bpw, > .speed_hz = speed_hz, > .tx_buf = buf, > .len = len, > }; > struct spi_message m; > size_t maxsize; > int ret; > > maxsize = tinydrm_spi_max_transfer_size(spi, 0); > > if (drm_debug & DRM_UT_DRIVER) > pr_debug("[drm:%s] bpw=%u, maxsize=%zu, transfers:\n", > __func__, bpw, maxsize); > > spi_message_init(&m); > m.spi = spi; > if (header) > spi_message_add_tail(header, &m); > spi_message_add_tail(&tr, &m); > > ret = spi_split_transfers_maxsize(spi->controller, &m, maxsize, > GFP_KERNEL); > if (ret) > return ret; > > tinydrm_dbg_spi_message(spi, &m); > > return spi_sync(spi, &m); > } > EXPORT_SYMBOL(tinydrm_spi_transfer); > > > Log: > [ 39.015644] [drm:mipi_dbi_fb_dirty [mipi_dbi]] Flushing [FB:36] x1=0, > x2=320, y1=0, y2=240 > > [ 39.018079] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2a, par=00 00 01 > 3f > [ 39.018129] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: > [ 39.018152] tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2a] > [ 39.018231] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: > [ 39.018248] tr(0): speed=10MHz, bpw=8, len=4, tx_buf=[00 00 01 3f] > > [ 39.018330] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2b, par=00 00 00 > ef > [ 39.018347] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: > [ 39.018362] tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2b] > [ 39.018396] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: > [ 39.018428] tr(0): speed=10MHz, bpw=8, len=4, tx_buf=[00 00 00 ef] > > [ 39.018487] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2c, len=153600 > [ 39.018502] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: > [ 39.018517] tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2c] > [ 39.018565] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: > [ 39.018594] tr(0): speed=48MHz, bpw=8, len=65532, tx_buf=[c6 18 c6 18 > c6 18 c6 18 c6 18 c6 18 c6 18 c6 18 ...] > [ 39.018608] tr(1): speed=48MHz, bpw=8, len=65532, tx_buf=[06 18 06 18 > 06 18 06 18 06 18 06 18 06 18 06 18 ...] > [ 39.018621] tr(2): speed=48MHz, bpw=8, len=22536, tx_buf=[10 82 10 82 > 10 82 10 82 10 82 10 82 18 e3 18 e3 ...] Hi Noralf, Yes this works but splitting in the spi subsystem doesn't seem to work. So this means that spi_split_transfers_maxsize is working. Should I just send in a patch with splitting done here in tinydrm? (I had thought we wanted to avoid splitting in the tinydrm helper). Thanks and regards, Meghana > > Noralf. > > _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2018-03-05 17:06 (unknown) Meghana Madhyastha @ 2018-03-05 19:24 ` Noralf Trønnes 0 siblings, 0 replies; 42+ messages in thread From: Noralf Trønnes @ 2018-03-05 19:24 UTC (permalink / raw) To: Meghana Madhyastha, Daniel Vetter, dri-devel Den 05.03.2018 18.06, skrev Meghana Madhyastha: > linux-spi@vger.kernel.org,Noralf Trønnes <noralf@tronnes.org>,Sean Paul <seanpaul@chromium.org>,kernel@martin.sperl.org > Cc: > Bcc: > Subject: Re: [PATCH v2 0/2] Chunk splitting of spi transfers > Reply-To: > In-Reply-To: <f6dbf3ca-4c1b-90cc-c4af-8889f7407180@tronnes.org> > > On Sun, Mar 04, 2018 at 06:38:42PM +0100, Noralf Trønnes wrote: >> Den 02.03.2018 12.11, skrev Meghana Madhyastha: >>> On Sun, Feb 25, 2018 at 02:19:10PM +0100, Lukas Wunner wrote: >>>> [cc += linux-rpi-kernel@lists.infradead.org] >>>> >>>> On Sat, Feb 24, 2018 at 06:15:59PM +0000, Meghana Madhyastha wrote: >>>>> I've added bcm2835_spi_transfer_one_message in spi-bcm2835. This calls >>>>> spi_split_transfers_maxsize to split large chunks for spi dma transfers. >>>>> I then removed chunk splitting in the tinydrm spi helper (as now the core >>>>> is handling the chunk splitting). However, although the SPI HW should be >>>>> able to accomodate up to 65535 bytes for dma transfers, the splitting of >>>>> chunks to 65535 bytes results in a dma transfer time out error. However, >>>>> when the chunks are split to < 64 bytes it seems to work fine. >>>> Hm, that is really odd, how did you test this exactly, what did you >>>> use as SPI slave? It contradicts our own experience, we're using >>>> Micrel KSZ8851 Ethernet chips as SPI slave on spi0 of a BCM2837 >>>> and can send/receive messages via DMA to the tune of several hundred >>>> bytes without any issues. In fact, for messages < 96 bytes, DMA is >>>> not used at all, so you've probably been using interrupt mode, >>>> see the BCM2835_SPI_DMA_MIN_LENGTH macro in spi-bcm2835.c. >>> Hi Lukas, >>> >>> I think you are right. I checked it and its not using the DMA mode which >>> is why its working with 64 bytes. >>> Noralf, that leaves us back to the >>> initial time out problem. I've tried doing the message splitting in >>> spi_sync as well as spi_pump_messages. Martin had explained that DMA >>> will wait for >>> the SPI HW to set the send_more_data line, but the SPI-HW itself will >>> stop triggering it when SPI_LEN is 0 causing DMA to wait forever. I >>> thought if we split it before itself, the SPI_LEN will not go to zero >>> thus preventing this problem, however it didn't work and started >>> hanging. So I'm a little uncertain as to how to proceed and debug what >>> exactly has caused the time out due to the asynchronous methods. >> I did a quick test and at least this is working: >> >> int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz, >> struct spi_transfer *header, u8 bpw, const void *buf, >> size_t len) >> { >> struct spi_transfer tr = { >> .bits_per_word = bpw, >> .speed_hz = speed_hz, >> .tx_buf = buf, >> .len = len, >> }; >> struct spi_message m; >> size_t maxsize; >> int ret; >> >> maxsize = tinydrm_spi_max_transfer_size(spi, 0); >> >> if (drm_debug & DRM_UT_DRIVER) >> pr_debug("[drm:%s] bpw=%u, maxsize=%zu, transfers:\n", >> __func__, bpw, maxsize); >> >> spi_message_init(&m); >> m.spi = spi; >> if (header) >> spi_message_add_tail(header, &m); >> spi_message_add_tail(&tr, &m); >> >> ret = spi_split_transfers_maxsize(spi->controller, &m, maxsize, >> GFP_KERNEL); >> if (ret) >> return ret; >> >> tinydrm_dbg_spi_message(spi, &m); >> >> return spi_sync(spi, &m); >> } >> EXPORT_SYMBOL(tinydrm_spi_transfer); >> >> >> Log: >> [ 39.015644] [drm:mipi_dbi_fb_dirty [mipi_dbi]] Flushing [FB:36] x1=0, >> x2=320, y1=0, y2=240 >> >> [ 39.018079] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2a, par=00 00 01 >> 3f >> [ 39.018129] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: >> [ 39.018152] tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2a] >> [ 39.018231] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: >> [ 39.018248] tr(0): speed=10MHz, bpw=8, len=4, tx_buf=[00 00 01 3f] >> >> [ 39.018330] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2b, par=00 00 00 >> ef >> [ 39.018347] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: >> [ 39.018362] tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2b] >> [ 39.018396] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: >> [ 39.018428] tr(0): speed=10MHz, bpw=8, len=4, tx_buf=[00 00 00 ef] >> >> [ 39.018487] [drm:mipi_dbi_typec3_command [mipi_dbi]] cmd=2c, len=153600 >> [ 39.018502] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: >> [ 39.018517] tr(0): speed=10MHz, bpw=8, len=1, tx_buf=[2c] >> [ 39.018565] [drm:tinydrm_spi_transfer] bpw=8, maxsize=65532, transfers: >> [ 39.018594] tr(0): speed=48MHz, bpw=8, len=65532, tx_buf=[c6 18 c6 18 >> c6 18 c6 18 c6 18 c6 18 c6 18 c6 18 ...] >> [ 39.018608] tr(1): speed=48MHz, bpw=8, len=65532, tx_buf=[06 18 06 18 >> 06 18 06 18 06 18 06 18 06 18 06 18 ...] >> [ 39.018621] tr(2): speed=48MHz, bpw=8, len=22536, tx_buf=[10 82 10 82 >> 10 82 10 82 10 82 10 82 18 e3 18 e3 ...] > Hi Noralf, > > Yes this works but splitting in the spi subsystem doesn't seem to work. > So this means that spi_split_transfers_maxsize is working. > Should I just send in a patch with splitting done here in tinydrm? (I > had thought we wanted to avoid splitting in the tinydrm helper). Oh, I assumed you didn't get this to work in any way. Yes, I prefer splitting without the client's knowledge. Looking at the code the splitting has to happen before spi_map_msg() is called. Have you tried to do it in the prepare_message callback? static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread) { <...> if (ctlr->prepare_message) { ret = ctlr->prepare_message(ctlr, ctlr->cur_msg); <...> ret = spi_map_msg(ctlr, ctlr->cur_msg); <...> ret = ctlr->transfer_one_message(ctlr, ctlr->cur_msg); <...> } There was something wrong with this email, it was missing subject and several recipients. Noralf. _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* (unknown), @ 2018-10-21 16:25 Michael Tirado 2018-10-22 0:26 ` Dave Airlie 0 siblings, 1 reply; 42+ messages in thread From: Michael Tirado @ 2018-10-21 16:25 UTC (permalink / raw) To: Airlied, dri-devel, LKML, kraxel, alexander.deucher, christian.koenig, David1.zhou, Hongbo.He Cc: seanpaul, Gustavo, maarten.lankhorst [-- Attachment #1: Type: text/plain, Size: 5516 bytes --] Mapping a drm "dumb" buffer fails on 32-bit system (i686) from what appears to be a truncated memory address that has been copied throughout several files. The bug manifests as an -EINVAL when calling mmap with the offset gathered from DRM_IOCTL_MODE_MAP_DUMB <-- DRM_IOCTL_MODE_ADDFB <-- DRM_IOCTL_MODE_CREATE_DUMB. I can provide test code if needed. The following patch will apply to 4.18 though I've only been able to test through qemu bochs driver and nouveau. Intel driver worked without any issues. I'm not sure if everyone is going to want to share a constant, and the whitespace is screwed up from gmail's awful javascript client, so let me know if I should resend this with any specific changes. I have also attached the file with preserved whitespace. --- linux-4.13.8/drivers/gpu/drm/bochs/bochs.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/bochs/bochs.h 2017-10-20 14:34:50.308633773 +0000 @@ -115,8 +115,6 @@ return container_of(gem, struct bochs_bo, gem); } -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo) { return drm_vma_node_offset_addr(&bo->bo.vma_node); --- linux-4.13.8/drivers/gpu/drm/nouveau/nouveau_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/nouveau/nouveau_drv.h 2017-10-20 14:34:51.581633751 +0000 @@ -57,8 +57,6 @@ struct nouveau_channel; struct platform_device; -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - #include "nouveau_fence.h" #include "nouveau_bios.h" --- linux-4.13.8/drivers/gpu/drm/ast/ast_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/ast/ast_drv.h 2017-10-20 14:34:50.289633773 +0000 @@ -356,8 +356,6 @@ uint32_t handle, uint64_t *offset); -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - int ast_mm_init(struct ast_private *ast); void ast_mm_fini(struct ast_private *ast); --- linux-4.13.8/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c 2017-10-20 14:34:50.644633767 +0000 @@ -21,8 +21,6 @@ #include "hibmc_drm_drv.h" -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - static inline struct hibmc_drm_private * hibmc_bdev(struct ttm_bo_device *bd) { --- linux-4.13.8/drivers/gpu/drm/virtio/virtgpu_ttm.c 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/virtio/virtgpu_ttm.c 2017-10-20 14:34:53.055633725 +0000 @@ -37,8 +37,6 @@ #include <linux/delay.h> -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - static struct virtio_gpu_device *virtio_gpu_get_vgdev(struct ttm_bo_device *bdev) { --- linux-4.13.8/drivers/gpu/drm/qxl/qxl_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/qxl/qxl_drv.h 2017-10-20 14:34:52.072633742 +0000 @@ -88,9 +88,6 @@ } \ } while (0) -#define DRM_FILE_OFFSET 0x100000000ULL -#define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT) - #define QXL_INTERRUPT_MASK (\ QXL_INTERRUPT_DISPLAY |\ QXL_INTERRUPT_CURSOR |\ --- linux-4.13.8/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 2017-10-20 14:34:43.264633895 +0000 @@ -48,3 +48,1 @@ -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - --- linux-4.13.8/drivers/gpu/drm/mgag200/mgag200_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/mgag200/mgag200_drv.h 2017-10-20 14:34:51.404633754 +0000 @@ -276,7 +276,6 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev); void mgag200_i2c_destroy(struct mga_i2c_chan *i2c); -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) void mgag200_ttm_placement(struct mgag200_bo *bo, int domain); static inline int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait) --- linux-4.13.8/drivers/gpu/drm/radeon/radeon_ttm.c 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/radeon/radeon_ttm.c 2017-10-20 14:34:52.588633733 +0000 @@ -45,8 +45,6 @@ #include "radeon_reg.h" #include "radeon.h" -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - static int radeon_ttm_debugfs_init(struct radeon_device *rdev); static void radeon_ttm_debugfs_fini(struct radeon_device *rdev); --- linux-4.13.8/drivers/gpu/drm/cirrus/cirrus_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/cirrus/cirrus_drv.h 2017-10-20 14:34:50.333633772 +0000 @@ -178,7 +178,6 @@ #define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base) -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) /* cirrus_mode.c */ void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, --- linux-4.13.8/include/drm/drmP.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/include/drm/drmP.h 2017-10-20 14:35:31.300633060 +0000 @@ -503,4 +503,10 @@ /* helper for handling conditionals in various for_each macros */ #define for_each_if(condition) if (!(condition)) {} else +#if BITS_PER_LONG == 64 +#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) +#else +#define DRM_FILE_PAGE_OFFSET (0x10000000ULL >> PAGE_SHIFT) +#endif + #endif [-- Attachment #2: drm_file_offset.patch --] [-- Type: application/octet-stream, Size: 4581 bytes --] --- linux-4.13.8/drivers/gpu/drm/bochs/bochs.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/bochs/bochs.h 2017-10-20 14:34:50.308633773 +0000 @@ -115,8 +115,6 @@ return container_of(gem, struct bochs_bo, gem); } -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo) { return drm_vma_node_offset_addr(&bo->bo.vma_node); --- linux-4.13.8/drivers/gpu/drm/nouveau/nouveau_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/nouveau/nouveau_drv.h 2017-10-20 14:34:51.581633751 +0000 @@ -57,8 +57,6 @@ struct nouveau_channel; struct platform_device; -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - #include "nouveau_fence.h" #include "nouveau_bios.h" --- linux-4.13.8/drivers/gpu/drm/ast/ast_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/ast/ast_drv.h 2017-10-20 14:34:50.289633773 +0000 @@ -356,8 +356,6 @@ uint32_t handle, uint64_t *offset); -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - int ast_mm_init(struct ast_private *ast); void ast_mm_fini(struct ast_private *ast); --- linux-4.13.8/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c 2017-10-20 14:34:50.644633767 +0000 @@ -21,8 +21,6 @@ #include "hibmc_drm_drv.h" -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - static inline struct hibmc_drm_private * hibmc_bdev(struct ttm_bo_device *bd) { --- linux-4.13.8/drivers/gpu/drm/virtio/virtgpu_ttm.c 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/virtio/virtgpu_ttm.c 2017-10-20 14:34:53.055633725 +0000 @@ -37,8 +37,6 @@ #include <linux/delay.h> -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - static struct virtio_gpu_device *virtio_gpu_get_vgdev(struct ttm_bo_device *bdev) { --- linux-4.13.8/drivers/gpu/drm/qxl/qxl_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/qxl/qxl_drv.h 2017-10-20 14:34:52.072633742 +0000 @@ -88,9 +88,6 @@ } \ } while (0) -#define DRM_FILE_OFFSET 0x100000000ULL -#define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT) - #define QXL_INTERRUPT_MASK (\ QXL_INTERRUPT_DISPLAY |\ QXL_INTERRUPT_CURSOR |\ --- linux-4.13.8/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 2017-10-20 14:34:43.264633895 +0000 @@ -48,3 +48,1 @@ -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - --- linux-4.13.8/drivers/gpu/drm/mgag200/mgag200_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/mgag200/mgag200_drv.h 2017-10-20 14:34:51.404633754 +0000 @@ -276,7 +276,6 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev); void mgag200_i2c_destroy(struct mga_i2c_chan *i2c); -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) void mgag200_ttm_placement(struct mgag200_bo *bo, int domain); static inline int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait) --- linux-4.13.8/drivers/gpu/drm/radeon/radeon_ttm.c 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/radeon/radeon_ttm.c 2017-10-20 14:34:52.588633733 +0000 @@ -45,8 +45,6 @@ #include "radeon_reg.h" #include "radeon.h" -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) - static int radeon_ttm_debugfs_init(struct radeon_device *rdev); static void radeon_ttm_debugfs_fini(struct radeon_device *rdev); --- linux-4.13.8/drivers/gpu/drm/cirrus/cirrus_drv.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/drivers/gpu/drm/cirrus/cirrus_drv.h 2017-10-20 14:34:50.333633772 +0000 @@ -178,7 +178,6 @@ #define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base) -#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) /* cirrus_mode.c */ void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, --- linux-4.13.8/include/drm/drmP.h 2017-10-18 07:38:33.000000000 +0000 +++ linux-4.13.8-modified/include/drm/drmP.h 2017-10-20 14:35:31.300633060 +0000 @@ -503,4 +503,10 @@ /* helper for handling conditionals in various for_each macros */ #define for_each_if(condition) if (!(condition)) {} else +#if BITS_PER_LONG == 64 +#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) +#else +#define DRM_FILE_PAGE_OFFSET (0x10000000ULL >> PAGE_SHIFT) +#endif + #endif ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2018-10-21 16:25 (unknown), Michael Tirado @ 2018-10-22 0:26 ` Dave Airlie 2018-10-21 20:23 ` Re: Michael Tirado 0 siblings, 1 reply; 42+ messages in thread From: Dave Airlie @ 2018-10-22 0:26 UTC (permalink / raw) To: mtirado418 Cc: Dave Airlie, LKML, dri-devel, Hongbo.He, Gerd Hoffmann, Deucher, Alexander, Sean Paul, Koenig, Christian On Mon, 22 Oct 2018 at 07:22, Michael Tirado <mtirado418@gmail.com> wrote: > > Mapping a drm "dumb" buffer fails on 32-bit system (i686) from what > appears to be a truncated memory address that has been copied > throughout several files. The bug manifests as an -EINVAL when calling > mmap with the offset gathered from DRM_IOCTL_MODE_MAP_DUMB <-- > DRM_IOCTL_MODE_ADDFB <-- DRM_IOCTL_MODE_CREATE_DUMB. I can provide > test code if needed. > > The following patch will apply to 4.18 though I've only been able to > test through qemu bochs driver and nouveau. Intel driver worked > without any issues. I'm not sure if everyone is going to want to > share a constant, and the whitespace is screwed up from gmail's awful > javascript client, so let me know if I should resend this with any > specific changes. I have also attached the file with preserved > whitespace. > This shouldn't be necessary, did someone misbackport the mmap changes without: drm: set FMODE_UNSIGNED_OFFSET for drm files Dave. _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2018-10-22 0:26 ` Dave Airlie @ 2018-10-21 20:23 ` Michael Tirado 2018-10-22 1:50 ` Re: Dave Airlie 0 siblings, 1 reply; 42+ messages in thread From: Michael Tirado @ 2018-10-21 20:23 UTC (permalink / raw) To: airlied Cc: Airlied, dri-devel, LKML, kraxel, alexander.deucher, christian.koenig, David1.zhou, Hongbo.He, Sean Paul, Gustavo, maarten.lankhorst On Mon, Oct 22, 2018 at 12:26 AM Dave Airlie <airlied@gmail.com> wrote: > > This shouldn't be necessary, did someone misbackport the mmap changes without: > > drm: set FMODE_UNSIGNED_OFFSET for drm files > > Dave. The latest kernel I have had to patch was a 4.18-rc6. I'll try with a newer 4.19 and let you know if it decides to work. If not I'll prepare a test case for demonstration on qemu-system-i386. ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2018-10-21 20:23 ` Re: Michael Tirado @ 2018-10-22 1:50 ` Dave Airlie 2018-10-21 22:20 ` Re: Michael Tirado 2018-10-23 1:47 ` Re: Michael Tirado 0 siblings, 2 replies; 42+ messages in thread From: Dave Airlie @ 2018-10-22 1:50 UTC (permalink / raw) To: mtirado418 Cc: Dave Airlie, LKML, dri-devel, Hongbo.He, Gerd Hoffmann, Deucher, Alexander, Sean Paul, Koenig, Christian On Mon, 22 Oct 2018 at 10:49, Michael Tirado <mtirado418@gmail.com> wrote: > > On Mon, Oct 22, 2018 at 12:26 AM Dave Airlie <airlied@gmail.com> wrote: > > > > This shouldn't be necessary, did someone misbackport the mmap changes without: > > > > drm: set FMODE_UNSIGNED_OFFSET for drm files > > > > Dave. > > The latest kernel I have had to patch was a 4.18-rc6. I'll try with a > newer 4.19 and let you know if it decides to work. If not I'll > prepare a test case for demonstration on qemu-system-i386. If you have custom userspace software, make sure it's using AC_SYS_LARGEFILE or whatever the equivalant is in your build system. 64-bit file offsets are important. Dave. _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2018-10-22 1:50 ` Re: Dave Airlie @ 2018-10-21 22:20 ` Michael Tirado 2018-10-23 1:47 ` Re: Michael Tirado 1 sibling, 0 replies; 42+ messages in thread From: Michael Tirado @ 2018-10-21 22:20 UTC (permalink / raw) To: Dave Airlie Cc: Airlied, dri-devel, LKML, kraxel, alexander.deucher, christian.koenig, David1.zhou, Hongbo.He, Sean Paul, Gustavo, maarten.lankhorst [-- Attachment #1: Type: text/plain, Size: 837 bytes --] On Mon, Oct 22, 2018 at 1:50 AM Dave Airlie <airlied@gmail.com> wrote: > > On Mon, 22 Oct 2018 at 10:49, Michael Tirado <mtirado418@gmail.com> wrote: > > > > On Mon, Oct 22, 2018 at 12:26 AM Dave Airlie <airlied@gmail.com> wrote: > > > > > > This shouldn't be necessary, did someone misbackport the mmap changes without: > If you have custom userspace software, make sure it's using > AC_SYS_LARGEFILE or whatever the equivalant is in your build system. > > 64-bit file offsets are important. > That fixed it! -D_FILE_OFFSET_BITS=64 is the pre-processor define needed. It's a bit more than unintuitive but I'm glad I don't need this stupid patch anymore, Thanks. In case anyone is further interested I have attached test program since I spent the last hour or so chopping it up anyway :S [ gcc -o kms -D_FILE_OFFSET_BITS=64 main.c ] [-- Attachment #2: main.c --] [-- Type: application/octet-stream, Size: 17153 bytes --] /* Copyright (C) 2017 Michael R. Tirado <mtirado418@gmail.com> -- GPLv3+ * * This program is libre software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. You should have * received a copy of the GNU General Public License version 3 * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <string.h> #include <unistd.h> #include <errno.h> #include <stdio.h> #include <malloc.h> #include <signal.h> #include <stdlib.h> #include <stdint.h> #include <stddef.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <stdio.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <drm/drm.h> #include <drm/drm_mode.h> #define STRERR strerror(errno) #ifndef PTRBITCOUNT #define PTRBITCOUNT 32 #endif /* kernel structs use __u64 for pointer types */ #if (PTRBITCOUNT == 32) #define ptr_from_krn(ptr) ((void *)(uint32_t)(ptr)) #define ptr_to_krn(ptr) ((uint32_t)(ptr)) #elif (PTRBITCOUNT == 64) #define ptr_from_krn(ptr) ((void *)(uint64_t)(ptr)) #define ptr_to_krn(ptr) ((uint64_t)(ptr)) #else #error "PTRBITCOUNT is undefined" #endif #ifndef MAX_FBS #define MAX_FBS 12 #endif #ifndef MAX_CRTCS #define MAX_CRTCS 12 #endif #ifndef MAX_CONNECTORS #define MAX_CONNECTORS 12 #endif #ifndef MAX_ENCODERS #define MAX_ENCODERS 12 #endif #ifndef MAX_PROPS #define MAX_PROPS 256 #endif #ifndef MAX_MODES #define MAX_MODES 256 #endif #if (PTRBITCOUNT == 32) #define drm_to_ptr(ptr) ((void *)(uint32_t)(ptr)) #define drm_from_ptr(ptr) ((uint32_t)(ptr)) #elif (PTRBITCOUNT == 64) #define drm_to_ptr(ptr) ((void *)(uint64_t)(ptr)) #define drm_from_ptr(ptr) ((uint64_t)(ptr)) #else #error "PTRBITCOUNT is undefined" #endif #define drm_alloc(size) (drm_from_ptr(calloc(1,size))) struct drm_buffer { uint32_t drm_id; uint32_t fb_id; uint32_t pitch; uint32_t width; uint32_t height; uint32_t depth; uint32_t bpp; char *addr; size_t size; }; struct drm_display { struct drm_mode_get_encoder encoder; struct drm_mode_crtc crtc; struct drm_mode_get_connector *conn; /* do we need array for multi-screen? */ struct drm_mode_modeinfo *modes; /* these both point to conn's mode array */ struct drm_mode_modeinfo *cur_mode; uint32_t cur_mode_idx; uint32_t mode_count; uint32_t conn_id; }; struct drm_kms { struct drm_display display; struct drm_buffer *sfb; struct drm_mode_card_res *res; int card_fd; }; /* get id out of drm_id_ptr */ static uint32_t drm_get_id(uint64_t addr, uint32_t idx) { return ((uint32_t *)drm_to_ptr(addr))[idx]; } static int free_mode_card_res(struct drm_mode_card_res *res) { if (!res) return -1; if (res->fb_id_ptr) free(drm_to_ptr(res->fb_id_ptr)); if (res->crtc_id_ptr) free(drm_to_ptr(res->crtc_id_ptr)); if (res->encoder_id_ptr) free(drm_to_ptr(res->encoder_id_ptr)); if (res->connector_id_ptr) free(drm_to_ptr(res->connector_id_ptr)); free(res); return 0; } static struct drm_mode_card_res *alloc_mode_card_res(int fd) { struct drm_mode_card_res res; struct drm_mode_card_res *ret; uint32_t count_fbs, count_crtcs, count_connectors, count_encoders; memset(&res, 0, sizeof(struct drm_mode_card_res)); if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) { printf("ioctl(DRM_IOCTL_MODE_GETRESOURCES, &res): %s\n", STRERR); return NULL; } if (res.count_fbs > MAX_FBS || res.count_crtcs > MAX_CRTCS || res.count_encoders > MAX_ENCODERS || res.count_connectors > MAX_CONNECTORS) { printf("resource limit reached, see defines.h\n"); return NULL; } if (res.count_fbs) { res.fb_id_ptr = drm_alloc(sizeof(uint32_t)*res.count_fbs); if (!res.fb_id_ptr) goto alloc_err; } if (res.count_crtcs) { res.crtc_id_ptr = drm_alloc(sizeof(uint32_t)*res.count_crtcs); if (!res.crtc_id_ptr) goto alloc_err; } if (res.count_encoders) { res.encoder_id_ptr = drm_alloc(sizeof(uint32_t)*res.count_encoders); if (!res.encoder_id_ptr) goto alloc_err; } if (res.count_connectors) { res.connector_id_ptr = drm_alloc(sizeof(uint32_t)*res.count_connectors); if (!res.connector_id_ptr) goto alloc_err; } count_fbs = res.count_fbs; count_crtcs = res.count_crtcs; count_encoders = res.count_encoders; count_connectors = res.count_connectors; if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res) == -1) { printf("ioctl(DRM_IOCTL_MODE_GETRESOURCES, &res): %s\n", STRERR); goto free_err; } if (count_fbs != res.count_fbs || count_crtcs != res.count_crtcs || count_encoders != res.count_encoders || count_connectors != res.count_connectors) { errno = EAGAIN; goto free_err; } ret = calloc(1, sizeof(struct drm_mode_card_res)); if (!ret) goto alloc_err; memcpy(ret, &res, sizeof(struct drm_mode_card_res)); return ret; alloc_err: errno = ENOMEM; free_err: free(drm_to_ptr(res.fb_id_ptr)); free(drm_to_ptr(res.crtc_id_ptr)); free(drm_to_ptr(res.connector_id_ptr)); free(drm_to_ptr(res.encoder_id_ptr)); return NULL; } static struct drm_mode_get_connector *alloc_connector(int fd, uint32_t conn_id) { struct drm_mode_get_connector conn; struct drm_mode_get_connector *ret; uint32_t count_modes, count_props, count_encoders; memset(&conn, 0, sizeof(struct drm_mode_get_connector)); conn.connector_id = conn_id; if (ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn) == -1) { printf("ioctl(DRM_IOCTL_MODE_GETCONNECTOR, &conn): %s\n", STRERR); return NULL; } if (conn.count_modes > MAX_MODES || conn.count_props > MAX_PROPS || conn.count_encoders > MAX_ENCODERS) { printf("resource limit reached, see defines.h\n"); return NULL; } if (conn.count_modes) { conn.modes_ptr = drm_alloc(sizeof(struct drm_mode_modeinfo) * conn.count_modes); if (!conn.modes_ptr) goto alloc_err; } if (conn.count_props) { conn.props_ptr = drm_alloc(sizeof(uint32_t)*conn.count_props); if (!conn.props_ptr) goto alloc_err; conn.prop_values_ptr = drm_alloc(sizeof(uint64_t)*conn.count_props); if (!conn.prop_values_ptr) goto alloc_err; } if (conn.count_encoders) { conn.encoders_ptr = drm_alloc(sizeof(uint32_t)*conn.count_encoders); if (!conn.encoders_ptr) goto alloc_err; } count_modes = conn.count_modes; count_props = conn.count_props; count_encoders = conn.count_encoders; if (ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn) == -1) { printf("ioctl(DRM_IOCTL_MODE_GETCONNECTOR, &conn): %s\n", STRERR); goto free_err; } if (count_modes != conn.count_modes || count_props != conn.count_props || count_encoders != conn.count_encoders) { errno = EAGAIN; goto free_err; } ret = calloc(1, sizeof(struct drm_mode_get_connector)); if (!ret) goto alloc_err; memcpy(ret, &conn, sizeof(struct drm_mode_get_connector)); return ret; alloc_err: errno = ENOMEM; free_err: free(drm_to_ptr(conn.modes_ptr)); free(drm_to_ptr(conn.props_ptr)); free(drm_to_ptr(conn.encoders_ptr)); free(drm_to_ptr(conn.prop_values_ptr)); return NULL; } static struct drm_mode_modeinfo *get_connector_modeinfo(struct drm_mode_get_connector *conn, uint32_t *count) { if (!conn || !count) return NULL; *count = conn->count_modes; return drm_to_ptr(conn->modes_ptr); } static int free_connector(struct drm_mode_get_connector *conn) { if (!conn) return -1; if (conn->modes_ptr) free(drm_to_ptr(conn->modes_ptr)); if (conn->props_ptr) free(drm_to_ptr(conn->props_ptr)); if (conn->encoders_ptr) free(drm_to_ptr(conn->encoders_ptr)); if (conn->prop_values_ptr) free(drm_to_ptr(conn->prop_values_ptr)); free(conn); return 0; } static int drm_kms_connect_sfb(struct drm_kms *self) { struct drm_display *display = &self->display; struct drm_mode_get_connector *conn; struct drm_mode_modeinfo *cur_mode; struct drm_mode_get_encoder *encoder; struct drm_mode_crtc *crtc; if (!display || !display->conn || !display->cur_mode || !self->sfb) return -1; conn = display->conn; cur_mode = display->cur_mode; encoder = &self->display.encoder; crtc = &self->display.crtc; memset(crtc, 0, sizeof(struct drm_mode_crtc)); memset(encoder, 0, sizeof(struct drm_mode_get_encoder)); /* XXX: there can be multiple encoders, have not investigated this much */ if (conn->encoder_id == 0) { printf("conn->encoder_id was 0, defaulting to encoder[0]\n"); conn->encoder_id = ((uint32_t *)drm_to_ptr(conn->encoders_ptr))[0]; } encoder->encoder_id = conn->encoder_id; if (ioctl(self->card_fd, DRM_IOCTL_MODE_GETENCODER, encoder) == -1) { printf("ioctl(DRM_IOCTL_MODE_GETENCODER): %s\n", STRERR); return -1; } if (encoder->crtc_id == 0) { printf("encoder->crtc_id was 0, defaulting to crtc[0]\n"); encoder->crtc_id = ((uint32_t *)drm_to_ptr(self->res->crtc_id_ptr))[0]; } crtc->crtc_id = encoder->crtc_id; if (ioctl(self->card_fd, DRM_IOCTL_MODE_GETCRTC, crtc) == -1) { printf("ioctl(DRM_IOCTL_MODE_GETCRTC): %s\n", STRERR); return -1; } /* set crtc mode */ crtc->fb_id = self->sfb->fb_id; crtc->set_connectors_ptr = drm_from_ptr((void *)&conn->connector_id); crtc->count_connectors = 1; crtc->mode = *cur_mode; /*printf("\nsetting mode:\n\n"); print_mode_modeinfo(cur_mode);*/ crtc->mode_valid = 1; if (ioctl(self->card_fd, DRM_IOCTL_MODE_SETCRTC, crtc) == -1) { printf("ioctl(DRM_IOCTL_MODE_SETCRTC): %s\n", STRERR); return -1; } return 0; } /* stupid frame buffer */ static struct drm_buffer *alloc_sfb(int card_fd, uint32_t width, uint32_t height, uint32_t depth, uint32_t bpp) { struct drm_mode_create_dumb cdumb; struct drm_mode_map_dumb moff; struct drm_mode_fb_cmd cmd; struct drm_buffer *ret; void *fbmap; memset(&cdumb, 0, sizeof(cdumb)); memset(&moff, 0, sizeof(moff)); memset(&cmd, 0, sizeof(cmd)); /* create dumb buffer */ cdumb.width = width; cdumb.height = height; cdumb.bpp = bpp; cdumb.flags = 0; cdumb.pitch = 0; cdumb.size = 0; cdumb.handle = 0; if (ioctl(card_fd, DRM_IOCTL_MODE_CREATE_DUMB, &cdumb) == -1) { printf("ioctl(DRM_IOCTL_MODE_CREATE_DUMB): %s\n", STRERR); return NULL; } /* add framebuffer object */ cmd.width = cdumb.width; cmd.height = cdumb.height; cmd.bpp = cdumb.bpp; cmd.pitch = cdumb.pitch; cmd.depth = depth; cmd.handle = cdumb.handle; if (ioctl(card_fd, DRM_IOCTL_MODE_ADDFB, &cmd) == -1) { printf("ioctl(DRM_IOCTL_MODE_ADDFB): %s\n", STRERR); ioctl(card_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &cdumb.handle); return NULL; } /* get mmap offset */ moff.handle = cdumb.handle; if (ioctl(card_fd, DRM_IOCTL_MODE_MAP_DUMB, &moff) == -1) { printf("ioctl(DRM_IOCTL_MODE_MAP_DUMB): %s\n", STRERR); ioctl(card_fd, DRM_IOCTL_MODE_RMFB, &cmd.fb_id); ioctl(card_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &cdumb.handle); return NULL; } /* XXX this is probably better off as MAP_PRIVATE, we can't prime * the main framebuffer if it's "dumb", AFAIK */ fbmap = mmap(0, (size_t)cdumb.size, PROT_READ|PROT_WRITE, MAP_SHARED, card_fd, (off_t)moff.offset); if (fbmap == MAP_FAILED) { printf("framebuffer mmap failed: %s\n", STRERR); ioctl(card_fd, DRM_IOCTL_MODE_RMFB, &cmd.fb_id); ioctl(card_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &cdumb.handle); return NULL; } ret = calloc(1, sizeof(struct drm_buffer)); if (!ret) { printf("-ENOMEM\n"); munmap(fbmap, cdumb.size); ioctl(card_fd, DRM_IOCTL_MODE_RMFB, &cmd.fb_id); ioctl(card_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &cdumb.handle); return NULL; } ret->addr = fbmap; ret->size = cdumb.size; ret->pitch = cdumb.pitch; ret->width = cdumb.width; ret->height = cdumb.height; ret->bpp = cdumb.bpp; ret->depth = cmd.depth; ret->fb_id = cmd.fb_id; ret->drm_id = cdumb.handle; memset(fbmap, 0x27, cdumb.size); return ret; } static int destroy_sfb(int card_fd, struct drm_buffer *sfb) { if (!sfb) return -1; if (munmap(sfb->addr, sfb->size) == -1) printf("munmap: %s\n", STRERR); if (ioctl(card_fd, DRM_IOCTL_MODE_RMFB, &sfb->fb_id)) printf("ioctl(DRM_IOCTL_MODE_RMFB): %s\n", STRERR); if (ioctl(card_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &sfb->drm_id)) printf("ioctl(DRM_IOCTL_MODE_DESTROY_DUMB): %s\n", STRERR); free(sfb); return 0; } static int card_set_master(int card_fd) { if (ioctl(card_fd, DRM_IOCTL_SET_MASTER, 0)) { printf("ioctl(DRM_IOCTL_SET_MASTER, 0): %s\n", STRERR); return -1; } return 0; } static int card_drop_master(int card_fd) { if (ioctl(card_fd, DRM_IOCTL_DROP_MASTER, 0)) { printf("ioctl(DRM_IOCTL_DROP_MASTER, 0): %s\n", STRERR); return -1; } return 0; } static int drm_display_destroy(struct drm_display *display) { if (display->conn) free_connector(display->conn); memset(display, 0, sizeof(struct drm_display)); return 0; } int drm_kms_destroy(struct drm_kms *self) { if (self->sfb) destroy_sfb(self->card_fd, self->sfb); if (self->res) free_mode_card_res(self->res); drm_display_destroy(&self->display); close(self->card_fd); memset(self, 0, sizeof(struct drm_kms)); free(self); return 0; } static int get_mode_idx(struct drm_mode_modeinfo *modes, uint16_t count, uint16_t width, uint16_t height, uint16_t refresh) { int i; int pick = -1; if (width == 0) width = 0xffff; if (height == 0) height = 0xffff; for (i = 0; i < count; ++i) { if (modes[i].hdisplay > width || modes[i].vdisplay > height) continue; /* pretend these radical modes don't exist for now */ if (modes[i].hdisplay % 16 == 0) { if (pick < 0) { pick = i; continue; } if (modes[i].hdisplay > modes[pick].hdisplay) pick = i; else if (modes[i].vdisplay > modes[pick].vdisplay) pick = i; else if (modes[i].hdisplay == modes[pick].hdisplay && modes[i].vdisplay == modes[pick].vdisplay) { if (abs(refresh - modes[i].vrefresh) < abs(refresh - modes[pick].vrefresh)) { pick = i; } } } } if (pick < 0) { printf("could not find any usable modes for (%dx%d@%dhz)\n", width, height, refresh); return -1; } return pick; } /* TODO handle hotplugging */ static int drm_display_load(struct drm_kms *self, uint16_t req_width, uint16_t req_height, uint16_t req_refresh, struct drm_display *out) { uint32_t conn_id; int idx = -1; /* FIXME uses primary connector? "0" */ conn_id = drm_get_id(self->res->connector_id_ptr, 0); out->conn = alloc_connector(self->card_fd, conn_id); if (!out->conn) { printf("unable to create drm connector structure\n"); return -1; } out->conn_id = conn_id; out->modes = get_connector_modeinfo(out->conn, &out->mode_count); idx = get_mode_idx(out->modes, out->mode_count, req_width, req_height, req_refresh); if (idx < 0) goto free_err; out->cur_mode_idx = (uint32_t)idx; out->cur_mode = &out->modes[out->cur_mode_idx]; return 0; free_err: drm_display_destroy(out); return -1; } struct drm_kms *drm_mode_create(char *devname, int no_connect, uint16_t req_width, uint16_t req_height, uint16_t req_refresh) { char devpath[128]; struct drm_kms *self; struct drm_mode_modeinfo *cur_mode; int card_fd; snprintf(devpath, sizeof(devpath), "/dev/dri/%s", devname); card_fd = open(devpath, O_RDWR|O_CLOEXEC); if (card_fd == -1) { printf("open(%s): %s\n", devpath, STRERR); return NULL; } if (card_set_master(card_fd)) { printf("card_set_master failed\n"); return NULL; } self = calloc(1, sizeof(struct drm_kms)); if (!self) return NULL; self->card_fd = card_fd; self->res = alloc_mode_card_res(card_fd); if (!self->res) { printf("unable to create drm structure\n"); goto free_err; } if (drm_display_load(self, req_width, req_height, req_refresh, &self->display)) { printf("drm_display_load failed\n"); goto free_err; } cur_mode = self->display.cur_mode; printf("connector(%d) using mode[%d] (%dx%d@%dhz)\n", self->display.conn_id, self->display.cur_mode_idx, cur_mode->hdisplay, cur_mode->vdisplay, cur_mode->vrefresh); /* buffer pitch must divide evenly by 16, * TODO check against bpp here when that is variable instead of 32 */ self->sfb = alloc_sfb(card_fd, cur_mode->hdisplay, cur_mode->vdisplay, 24, 32); if (!self->sfb) { printf("alloc_sfb failed\n"); goto free_err; } if (!no_connect && drm_kms_connect_sfb(self)) { printf("drm_kms_connect_sfb failed\n"); goto free_err; } return self; free_err: drm_kms_destroy(self); return NULL; } int main(int argc, char *argv[]) { int ret = -1; struct drm_kms *card0; /*card0 = drm_mode_create("card0", g_srv_opts.inactive_vt, g_srv_opts.request_width, g_srv_opts.request_height, g_srv_opts.request_refresh);*/ /* do not connect to vt */ card0 = drm_mode_create("card0", 1, 640, 480, 60); if (card0 == NULL) { printf("drm_mode_create failed\n"); return -1; } drm_kms_destroy(card0); printf("looks ok, returning 0\n"); return 0; } ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2018-10-22 1:50 ` Re: Dave Airlie 2018-10-21 22:20 ` Re: Michael Tirado @ 2018-10-23 1:47 ` Michael Tirado 2018-10-23 6:23 ` Re: Dave Airlie 1 sibling, 1 reply; 42+ messages in thread From: Michael Tirado @ 2018-10-23 1:47 UTC (permalink / raw) To: Dave Airlie, LKML, dri-devel That preprocessor define worked but I'm still confused about this DRM_FILE_PAGE_OFFSET thing. Check out drivers/gpu/drm/drm_gem.c right above drm_gem_init. --- /* * We make up offsets for buffer objects so we can recognize them at * mmap time. */ /* pgoff in mmap is an unsigned long, so we need to make sure that * the faked up offset will fit */ #if BITS_PER_LONG == 64 #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1) #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16) #else #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1) #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16) #endif --- Why is having a 64-bit file offsets critical, causing -EINVAL on mmap? What problems might be associated with using (0x10000000UL >> PAGE_SHIFT) ? On Mon, Oct 22, 2018 at 1:50 AM Dave Airlie <airlied@gmail.com> wrote: > > On Mon, 22 Oct 2018 at 10:49, Michael Tirado <mtirado418@gmail.com> wrote: > > > > On Mon, Oct 22, 2018 at 12:26 AM Dave Airlie <airlied@gmail.com> wrote: > > > > > > This shouldn't be necessary, did someone misbackport the mmap changes without: > > > > > > drm: set FMODE_UNSIGNED_OFFSET for drm files > > > > > > Dave. > > > > The latest kernel I have had to patch was a 4.18-rc6. I'll try with a > > newer 4.19 and let you know if it decides to work. If not I'll > > prepare a test case for demonstration on qemu-system-i386. > > If you have custom userspace software, make sure it's using > AC_SYS_LARGEFILE or whatever the equivalant is in your build system. > > 64-bit file offsets are important. > > Dave. ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2018-10-23 1:47 ` Re: Michael Tirado @ 2018-10-23 6:23 ` Dave Airlie 0 siblings, 0 replies; 42+ messages in thread From: Dave Airlie @ 2018-10-23 6:23 UTC (permalink / raw) To: mtirado418; +Cc: LKML, dri-devel On Tue, 23 Oct 2018 at 16:13, Michael Tirado <mtirado418@gmail.com> wrote: > > That preprocessor define worked but I'm still confused about this > DRM_FILE_PAGE_OFFSET thing. Check out drivers/gpu/drm/drm_gem.c > right above drm_gem_init. > > --- > > /* > * We make up offsets for buffer objects so we can recognize them at > * mmap time. > */ > > /* pgoff in mmap is an unsigned long, so we need to make sure that > * the faked up offset will fit > */ > > #if BITS_PER_LONG == 64 > #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1) > #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16) > #else > #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1) > #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16) > #endif > > > --- > > Why is having a 64-bit file offsets critical, causing -EINVAL on mmap? > What problems might be associated with using (0x10000000UL >> > PAGE_SHIFT) ? a) it finds people not using the correct userspace defines. mostly libdrm should handle this, and possibly mesa. b) there used to be legacy maps below that address on older drivers, so we decided to never put stuff in the first 32-bit range that they could clash with. Dave. _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
[parent not found: <86d0ec$ae4ffc@fmsmga001.fm.intel.com>]
* Re: [not found] <86d0ec$ae4ffc@fmsmga001.fm.intel.com> @ 2020-02-26 12:08 ` Linus Walleij 2020-02-26 14:34 ` Re: Ville Syrjälä 0 siblings, 1 reply; 42+ messages in thread From: Linus Walleij @ 2020-02-26 12:08 UTC (permalink / raw) To: Ville Syrjälä Cc: Josh Wu, Bhuvanchandra DV, Neil Armstrong, nouveau, Guido Günther, Paul Kocialkowski, open list:DRM PANEL DRIVERS, Gustaf Lindström, Andrzej Hajda, Thierry Reding, Laurent Pinchart, Sam Ravnborg, Marian-Cristian Rotariu, Jagan Teki, Thomas Hellstrom, Joonyoung Shim, Jonathan Marek, Stefan Mavrodiev, Adam Ford, Jerry Han, VMware Graphics, Ben Skeggs, H. Nikolaus Schaller, Robert Chiras, Heiko Schocher, Icenowy Zheng, Jonas Karlman, intel-gfx, Alexandre Courbot, open list:ARM/Amlogic Meson..., Vincent Abriou, Andreas Pretzsch, Jernej Skrabec, Alex Gonzalez, Purism Kernel Team, Boris Brezillon, Seung-Woo Kim, Christoph Fritz, Kyungmin Park, Heiko Stuebner, Eugen Hristev, Giulio Benetti On Wed, Feb 26, 2020 at 12:57 PM Ville Syrjälä <ville.syrjala@linux.intel.com> wrote: > On Tue, Feb 25, 2020 at 10:52:25PM +0100, Linus Walleij wrote: > > I have long suspected that a whole bunch of the "simple" displays > > are not simple but contains a display controller and memory. > > That means that the speed over the link to the display and > > actual refresh rate on the actual display is asymmetric because > > well we are just updating a RAM, the resolution just limits how > > much data we are sending, the clock limits the speed on the > > bus over to the RAM on the other side. > > IMO even in command mode mode->clock should probably be the actual > dotclock used by the display. If there's another clock for the bus > speed/etc. it should be stored somewhere else. Good point. For the DSI panels we have the field hs_rate for the HS clock in struct mipi_dsi_device which is based on exactly this reasoning. And that is what I actually use for setting the HS clock. The problem is however that we in many cases have so substandard documentation of these panels that we have absolutely no idea about the dotclock. Maybe we should just set it to 0 in these cases? Yours, Linus Walleij _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2020-02-26 12:08 ` Re: Linus Walleij @ 2020-02-26 14:34 ` Ville Syrjälä 2020-02-26 14:56 ` Re: Linus Walleij 0 siblings, 1 reply; 42+ messages in thread From: Ville Syrjälä @ 2020-02-26 14:34 UTC (permalink / raw) To: Linus Walleij Cc: Josh Wu, Bhuvanchandra DV, Neil Armstrong, nouveau, Guido Günther, Paul Kocialkowski, open list:DRM PANEL DRIVERS, Gustaf Lindström, Andrzej Hajda, Thierry Reding, Laurent Pinchart, Sam Ravnborg, Marian-Cristian Rotariu, Jagan Teki, Thomas Hellstrom, Joonyoung Shim, Jonathan Marek, Stefan Mavrodiev, Adam Ford, Jerry Han, VMware Graphics, Ben Skeggs, H. Nikolaus Schaller, Robert Chiras, Heiko Schocher, Icenowy Zheng, Jonas Karlman, intel-gfx, Alexandre Courbot, open list:ARM/Amlogic Meson..., Vincent Abriou, Andreas Pretzsch, Jernej Skrabec, Alex Gonzalez, Purism Kernel Team, Boris Brezillon, Seung-Woo Kim, Christoph Fritz, Kyungmin Park, Heiko Stuebner, Eugen Hristev, Giulio Benetti On Wed, Feb 26, 2020 at 01:08:06PM +0100, Linus Walleij wrote: > On Wed, Feb 26, 2020 at 12:57 PM Ville Syrjälä > <ville.syrjala@linux.intel.com> wrote: > > On Tue, Feb 25, 2020 at 10:52:25PM +0100, Linus Walleij wrote: > > > > I have long suspected that a whole bunch of the "simple" displays > > > are not simple but contains a display controller and memory. > > > That means that the speed over the link to the display and > > > actual refresh rate on the actual display is asymmetric because > > > well we are just updating a RAM, the resolution just limits how > > > much data we are sending, the clock limits the speed on the > > > bus over to the RAM on the other side. > > > > IMO even in command mode mode->clock should probably be the actual > > dotclock used by the display. If there's another clock for the bus > > speed/etc. it should be stored somewhere else. > > Good point. For the DSI panels we have the field hs_rate > for the HS clock in struct mipi_dsi_device which is based > on exactly this reasoning. And that is what I actually use for > setting the HS clock. > > The problem is however that we in many cases have so > substandard documentation of these panels that we have > absolutely no idea about the dotclock. Maybe we should > just set it to 0 in these cases? Don't you always have a TE interrupt or something like that available? Could just measure it from that if no better information is available? -- Ville Syrjälä Intel _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2020-02-26 14:34 ` Re: Ville Syrjälä @ 2020-02-26 14:56 ` Linus Walleij 2020-02-26 15:08 ` Re: Ville Syrjälä 0 siblings, 1 reply; 42+ messages in thread From: Linus Walleij @ 2020-02-26 14:56 UTC (permalink / raw) To: Ville Syrjälä Cc: Josh Wu, Bhuvanchandra DV, Neil Armstrong, nouveau, Guido Günther, Paul Kocialkowski, open list:DRM PANEL DRIVERS, Gustaf Lindström, Andrzej Hajda, Thierry Reding, Laurent Pinchart, Sam Ravnborg, Marian-Cristian Rotariu, Jagan Teki, Thomas Hellstrom, Joonyoung Shim, Jonathan Marek, Stefan Mavrodiev, Adam Ford, Jerry Han, VMware Graphics, Ben Skeggs, H. Nikolaus Schaller, Robert Chiras, Heiko Schocher, Icenowy Zheng, Jonas Karlman, intel-gfx, Alexandre Courbot, open list:ARM/Amlogic Meson..., Vincent Abriou, Andreas Pretzsch, Jernej Skrabec, Alex Gonzalez, Purism Kernel Team, Boris Brezillon, Seung-Woo Kim, Christoph Fritz, Kyungmin Park, Heiko Stuebner, Eugen Hristev, Giulio Benetti On Wed, Feb 26, 2020 at 3:34 PM Ville Syrjälä <ville.syrjala@linux.intel.com> wrote: > On Wed, Feb 26, 2020 at 01:08:06PM +0100, Linus Walleij wrote: > > On Wed, Feb 26, 2020 at 12:57 PM Ville Syrjälä > > <ville.syrjala@linux.intel.com> wrote: > > > On Tue, Feb 25, 2020 at 10:52:25PM +0100, Linus Walleij wrote: > > > > > > I have long suspected that a whole bunch of the "simple" displays > > > > are not simple but contains a display controller and memory. > > > > That means that the speed over the link to the display and > > > > actual refresh rate on the actual display is asymmetric because > > > > well we are just updating a RAM, the resolution just limits how > > > > much data we are sending, the clock limits the speed on the > > > > bus over to the RAM on the other side. > > > > > > IMO even in command mode mode->clock should probably be the actual > > > dotclock used by the display. If there's another clock for the bus > > > speed/etc. it should be stored somewhere else. > > > > Good point. For the DSI panels we have the field hs_rate > > for the HS clock in struct mipi_dsi_device which is based > > on exactly this reasoning. And that is what I actually use for > > setting the HS clock. > > > > The problem is however that we in many cases have so > > substandard documentation of these panels that we have > > absolutely no idea about the dotclock. Maybe we should > > just set it to 0 in these cases? > > Don't you always have a TE interrupt or something like that > available? Could just measure it from that if no better > information is available? Yes and I did exactly that, so that is why this comment is in the driver: static const struct drm_display_mode sony_acx424akp_cmd_mode = { (...) /* * Some desired refresh rate, experiments at the maximum "pixel" * clock speed (HS clock 420 MHz) yields around 117Hz. */ .vrefresh = 60, I got a review comment at the time saying 117 Hz was weird. We didn't reach a proper conclusion on this: https://lore.kernel.org/dri-devel/CACRpkdYW3YNPSNMY3A44GQn8DqK-n9TLvr7uipF7LM_DHZ5=Lg@mail.gmail.com/ Thierry wasn't sure if 60Hz was good or not, so I just had to go with something. We could calculate the resulting pixel clock for ~117 Hz with this resolution and put that in the clock field but ... don't know what is the best? Yours, Linus Walleij _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2020-02-26 14:56 ` Re: Linus Walleij @ 2020-02-26 15:08 ` Ville Syrjälä 0 siblings, 0 replies; 42+ messages in thread From: Ville Syrjälä @ 2020-02-26 15:08 UTC (permalink / raw) To: Linus Walleij Cc: Josh Wu, Bhuvanchandra DV, Neil Armstrong, nouveau, Guido Günther, Paul Kocialkowski, open list:DRM PANEL DRIVERS, Gustaf Lindström, Andrzej Hajda, Thierry Reding, Laurent Pinchart, Sam Ravnborg, Marian-Cristian Rotariu, Jagan Teki, Thomas Hellstrom, Joonyoung Shim, Jonathan Marek, Stefan Mavrodiev, Adam Ford, Jerry Han, VMware Graphics, Ben Skeggs, H. Nikolaus Schaller, Robert Chiras, Heiko Schocher, Icenowy Zheng, Jonas Karlman, intel-gfx, Alexandre Courbot, open list:ARM/Amlogic Meson..., Vincent Abriou, Andreas Pretzsch, Jernej Skrabec, Alex Gonzalez, Purism Kernel Team, Boris Brezillon, Seung-Woo Kim, Christoph Fritz, Kyungmin Park, Heiko Stuebner, Eugen Hristev, Giulio Benetti On Wed, Feb 26, 2020 at 03:56:36PM +0100, Linus Walleij wrote: > On Wed, Feb 26, 2020 at 3:34 PM Ville Syrjälä > <ville.syrjala@linux.intel.com> wrote: > > On Wed, Feb 26, 2020 at 01:08:06PM +0100, Linus Walleij wrote: > > > On Wed, Feb 26, 2020 at 12:57 PM Ville Syrjälä > > > <ville.syrjala@linux.intel.com> wrote: > > > > On Tue, Feb 25, 2020 at 10:52:25PM +0100, Linus Walleij wrote: > > > > > > > > I have long suspected that a whole bunch of the "simple" displays > > > > > are not simple but contains a display controller and memory. > > > > > That means that the speed over the link to the display and > > > > > actual refresh rate on the actual display is asymmetric because > > > > > well we are just updating a RAM, the resolution just limits how > > > > > much data we are sending, the clock limits the speed on the > > > > > bus over to the RAM on the other side. > > > > > > > > IMO even in command mode mode->clock should probably be the actual > > > > dotclock used by the display. If there's another clock for the bus > > > > speed/etc. it should be stored somewhere else. > > > > > > Good point. For the DSI panels we have the field hs_rate > > > for the HS clock in struct mipi_dsi_device which is based > > > on exactly this reasoning. And that is what I actually use for > > > setting the HS clock. > > > > > > The problem is however that we in many cases have so > > > substandard documentation of these panels that we have > > > absolutely no idea about the dotclock. Maybe we should > > > just set it to 0 in these cases? > > > > Don't you always have a TE interrupt or something like that > > available? Could just measure it from that if no better > > information is available? > > Yes and I did exactly that, so that is why this comment is in > the driver: > > static const struct drm_display_mode sony_acx424akp_cmd_mode = { > (...) > /* > * Some desired refresh rate, experiments at the maximum "pixel" > * clock speed (HS clock 420 MHz) yields around 117Hz. > */ > .vrefresh = 60, > > I got a review comment at the time saying 117 Hz was weird. > We didn't reach a proper conclusion on this: > https://lore.kernel.org/dri-devel/CACRpkdYW3YNPSNMY3A44GQn8DqK-n9TLvr7uipF7LM_DHZ5=Lg@mail.gmail.com/ > > Thierry wasn't sure if 60Hz was good or not, so I just had to > go with something. > > We could calculate the resulting pixel clock for ~117 Hz with > this resolution and put that in the clock field but ... don't know > what is the best? I would vote for that approach. -- Ville Syrjälä Intel _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* (no subject) @ 2020-09-15 2:40 Dave Airlie 2020-09-15 7:53 ` Christian König 0 siblings, 1 reply; 42+ messages in thread From: Dave Airlie @ 2020-09-15 2:40 UTC (permalink / raw) To: dri-devel; +Cc: christian.koenig, bskeggs The goal here is to make the ttm_tt object just represent a memory backing store, and now whether the store is bound to a global translation table. It moves binding up to the bo level. There's a lot more work on removing the global TT from the core of TTM, but this seems like a good start. Dave. _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2020-09-15 2:40 Dave Airlie @ 2020-09-15 7:53 ` Christian König 0 siblings, 0 replies; 42+ messages in thread From: Christian König @ 2020-09-15 7:53 UTC (permalink / raw) To: dri-devel; +Cc: bskeggs Reviewed-by: Christian König <christian.koenig@amd.com> for patches #1, #3 and #5-#7. Minor comments on the other two. Christian. Am 15.09.20 um 04:40 schrieb Dave Airlie: > The goal here is to make the ttm_tt object just represent a > memory backing store, and now whether the store is bound to a > global translation table. It moves binding up to the bo level. > > There's a lot more work on removing the global TT from the core > of TTM, but this seems like a good start. > > Dave. > > _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
[parent not found: <20201008181606.460499-1-sandy.8925@gmail.com>]
* Re: [not found] <20201008181606.460499-1-sandy.8925@gmail.com> @ 2020-10-09 6:47 ` Thomas Zimmermann 2020-10-09 7:14 ` Re: Thomas Zimmermann 0 siblings, 1 reply; 42+ messages in thread From: Thomas Zimmermann @ 2020-10-09 6:47 UTC (permalink / raw) To: sandy.8925, alexander.deucher; +Cc: dri-devel [-- Attachment #1.1.1: Type: text/plain, Size: 559 bytes --] NACK for the entire lack of any form of commit description. Am 08.10.20 um 20:16 schrieb sandy.8925@gmail.com: > Signed-off-by: Sandeep Raghuraman <sandy.8925@gmail.com> > > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel > -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer [-- Attachment #1.2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 516 bytes --] [-- Attachment #2: Type: text/plain, Size: 160 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: Re: 2020-10-09 6:47 ` Re: Thomas Zimmermann @ 2020-10-09 7:14 ` Thomas Zimmermann 2020-10-09 7:38 ` Re: Sandeep Raghuraman 0 siblings, 1 reply; 42+ messages in thread From: Thomas Zimmermann @ 2020-10-09 7:14 UTC (permalink / raw) To: sandy.8925, alexander.deucher; +Cc: dri-devel [-- Attachment #1.1.1: Type: text/plain, Size: 1038 bytes --] Hi Am 09.10.20 um 08:47 schrieb Thomas Zimmermann: > NACK for the entire lack of any form of commit description. Please see the documentation at [1] on how to describe the changes and getting your patches merged. Best regards Thomas [1] https://dri.freedesktop.org/docs/drm/process/submitting-patches.html#describe-your-changes > > Am 08.10.20 um 20:16 schrieb sandy.8925@gmail.com: >> Signed-off-by: Sandeep Raghuraman <sandy.8925@gmail.com> >> >> >> _______________________________________________ >> dri-devel mailing list >> dri-devel@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/dri-devel >> > > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel > -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer [-- Attachment #1.2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 516 bytes --] [-- Attachment #2: Type: text/plain, Size: 160 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2020-10-09 7:14 ` Re: Thomas Zimmermann @ 2020-10-09 7:38 ` Sandeep Raghuraman 2020-10-09 7:51 ` Re: Thomas Zimmermann 0 siblings, 1 reply; 42+ messages in thread From: Sandeep Raghuraman @ 2020-10-09 7:38 UTC (permalink / raw) To: Thomas Zimmermann, alexander.deucher; +Cc: dri-devel On 10/9/20 12:44 PM, Thomas Zimmermann wrote: > Hi > > Am 09.10.20 um 08:47 schrieb Thomas Zimmermann: >> NACK for the entire lack of any form of commit description. > > Please see the documentation at [1] on how to describe the changes and > getting your patches merged. Yes, I tried to use git send-email to send patches this time, and it resulted in this disaster. I'll stick to sending them through Thunderbird. > > Best regards > Thomas > > [1] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2020-10-09 7:38 ` Re: Sandeep Raghuraman @ 2020-10-09 7:51 ` Thomas Zimmermann 2020-10-09 15:48 ` Re: Alex Deucher 0 siblings, 1 reply; 42+ messages in thread From: Thomas Zimmermann @ 2020-10-09 7:51 UTC (permalink / raw) To: Sandeep Raghuraman, alexander.deucher; +Cc: dri-devel [-- Attachment #1.1.1: Type: text/plain, Size: 1328 bytes --] Hi Am 09.10.20 um 09:38 schrieb Sandeep Raghuraman: > > > On 10/9/20 12:44 PM, Thomas Zimmermann wrote: >> Hi >> >> Am 09.10.20 um 08:47 schrieb Thomas Zimmermann: >>> NACK for the entire lack of any form of commit description. >> >> Please see the documentation at [1] on how to describe the changes and >> getting your patches merged. > > Yes, I tried to use git send-email to send patches this time, and it resulted in this disaster. I'll stick to sending them through Thunderbird. What's the problem with send-email? A typical call for your patchset would look like git send-mail <upstream-branch>...HEAD --cover-letter --annotate --to=... --cc=... That allows you to write the cover letter and have it sent out. IIRC you need ot set $EDITOR to your favorite text editor; and configure the SMTP server in ~/.gitconfig, under [sendemail]. Best regards Thomas > >> >> Best regards >> Thomas >> >> [1] > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel > -- Thomas Zimmermann Graphics Driver Developer SUSE Software Solutions Germany GmbH Maxfeldstr. 5, 90409 Nürnberg, Germany (HRB 36809, AG Nürnberg) Geschäftsführer: Felix Imendörffer [-- Attachment #1.2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 516 bytes --] [-- Attachment #2: Type: text/plain, Size: 160 bytes --] _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2020-10-09 7:51 ` Re: Thomas Zimmermann @ 2020-10-09 15:48 ` Alex Deucher 0 siblings, 0 replies; 42+ messages in thread From: Alex Deucher @ 2020-10-09 15:48 UTC (permalink / raw) To: Thomas Zimmermann Cc: Deucher, Alexander, Sandeep Raghuraman, Maling list - DRI developers On Fri, Oct 9, 2020 at 3:51 AM Thomas Zimmermann <tzimmermann@suse.de> wrote: > > Hi > > Am 09.10.20 um 09:38 schrieb Sandeep Raghuraman: > > > > > > On 10/9/20 12:44 PM, Thomas Zimmermann wrote: > >> Hi > >> > >> Am 09.10.20 um 08:47 schrieb Thomas Zimmermann: > >>> NACK for the entire lack of any form of commit description. > >> > >> Please see the documentation at [1] on how to describe the changes and > >> getting your patches merged. > > > > Yes, I tried to use git send-email to send patches this time, and it resulted in this disaster. I'll stick to sending them through Thunderbird. > > What's the problem with send-email? > > A typical call for your patchset would look like > > git send-mail <upstream-branch>...HEAD --cover-letter --annotate > --to=... --cc=... > > That allows you to write the cover letter and have it sent out. IIRC you > need ot set $EDITOR to your favorite text editor; and configure the SMTP > server in ~/.gitconfig, under [sendemail]. > You can also do `git format-patch -3 --cover-letter` and manually edit the coverletter as needed then send them with git send-email. Alex > Best regards > Thomas > > > > >> > >> Best regards > >> Thomas > >> > >> [1] > > _______________________________________________ > > dri-devel mailing list > > dri-devel@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/dri-devel > > > > -- > Thomas Zimmermann > Graphics Driver Developer > SUSE Software Solutions Germany GmbH > Maxfeldstr. 5, 90409 Nürnberg, Germany > (HRB 36809, AG Nürnberg) > Geschäftsführer: Felix Imendörffer > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel ^ permalink raw reply [flat|nested] 42+ messages in thread
* (no subject) @ 2021-05-15 22:57 Dmitry Baryshkov 2021-06-02 21:45 ` Dmitry Baryshkov 0 siblings, 1 reply; 42+ messages in thread From: Dmitry Baryshkov @ 2021-05-15 22:57 UTC (permalink / raw) To: Bjorn Andersson, Rob Clark, Sean Paul, Abhinav Kumar Cc: Jonathan Marek, Stephen Boyd, linux-arm-msm, dri-devel, David Airlie, freedreno From Dmitry Baryshkov <dmitry.baryshkov@linaro.org> # This line is ignored. From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Reply-To: Subject: [PATCH v2 0/6] drm/msm/dpu: simplify RM code In-Reply-To: There is no need to request most of hardware blocks through the resource manager (RM), since typically there is 1:1 or N:1 relationship between corresponding blocks. Each LM is tied to the single PP. Each MERGE_3D can be used by the specified pair of PPs. Each DSPP is also tied to single LM. So instead of allocating them through the RM, get them via static configuration. Depends on: https://lore.kernel.org/linux-arm-msm/20210515190909.1809050-1-dmitry.baryshkov@linaro.org Changes since v1: - Split into separate patch series to ease review. ---------------------------------------------------------------- Dmitry Baryshkov (6): drm/msm/dpu: get DSPP blocks directly rather than through RM drm/msm/dpu: get MERGE_3D blocks directly rather than through RM drm/msm/dpu: get PINGPONG blocks directly rather than through RM drm/msm/dpu: get INTF blocks directly rather than through RM drm/msm/dpu: drop unused lm_max_width from RM drm/msm/dpu: simplify peer LM handling drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 54 +--- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 8 - drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 5 - .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 8 - .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 8 - drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h | 4 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 53 +++- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 5 +- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 310 ++------------------- drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 18 +- drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 9 +- 16 files changed, 115 insertions(+), 401 deletions(-) ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2021-05-15 22:57 Dmitry Baryshkov @ 2021-06-02 21:45 ` Dmitry Baryshkov 0 siblings, 0 replies; 42+ messages in thread From: Dmitry Baryshkov @ 2021-06-02 21:45 UTC (permalink / raw) To: Bjorn Andersson, Rob Clark, Sean Paul, Abhinav Kumar Cc: Jonathan Marek, Stephen Boyd, linux-arm-msm, dri-devel, David Airlie, freedreno On 16/05/2021 01:57, Dmitry Baryshkov wrote: > From Dmitry Baryshkov <dmitry.baryshkov@linaro.org> # This line is ignored. > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> > Reply-To: > Subject: [PATCH v2 0/6] drm/msm/dpu: simplify RM code > In-Reply-To: > > There is no need to request most of hardware blocks through the resource > manager (RM), since typically there is 1:1 or N:1 relationship between > corresponding blocks. Each LM is tied to the single PP. Each MERGE_3D > can be used by the specified pair of PPs. Each DSPP is also tied to > single LM. So instead of allocating them through the RM, get them via > static configuration. > > Depends on: https://lore.kernel.org/linux-arm-msm/20210515190909.1809050-1-dmitry.baryshkov@linaro.org > > Changes since v1: > - Split into separate patch series to ease review. Another gracious ping, now for this series. I want to send next version with minor changes, but I'd like to hear your overall opinion before doing that. > > ---------------------------------------------------------------- > Dmitry Baryshkov (6): > drm/msm/dpu: get DSPP blocks directly rather than through RM > drm/msm/dpu: get MERGE_3D blocks directly rather than through RM > drm/msm/dpu: get PINGPONG blocks directly rather than through RM > drm/msm/dpu: get INTF blocks directly rather than through RM > drm/msm/dpu: drop unused lm_max_width from RM > drm/msm/dpu: simplify peer LM handling > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 54 +--- > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 8 - > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 5 - > .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 8 - > .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 8 - > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 2 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 4 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 7 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c | 7 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h | 4 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 53 +++- > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 5 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 310 ++------------------- > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 18 +- > drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 9 +- > 16 files changed, 115 insertions(+), 401 deletions(-) > > -- With best wishes Dmitry ^ permalink raw reply [flat|nested] 42+ messages in thread
[parent not found: <CAGsV3ysM+p_HAq+LgOe4db09e+zRtvELHUQzCjF8FVE2UF+3Ow@mail.gmail.com>]
* Re: [not found] <CAGsV3ysM+p_HAq+LgOe4db09e+zRtvELHUQzCjF8FVE2UF+3Ow@mail.gmail.com> @ 2021-06-29 13:52 ` Alex Deucher 0 siblings, 0 replies; 42+ messages in thread From: Alex Deucher @ 2021-06-29 13:52 UTC (permalink / raw) To: shashank singh; +Cc: Maling list - DRI developers Yes, please see this page for more information: https://www.x.org/wiki/XorgEVoC/ Alex On Mon, Jun 21, 2021 at 2:26 PM shashank singh <shashanksingh819@gmail.com> wrote: > > Hello everyone, my name is Shashank Singh. I hope this is the right platform to reach out to the 'X.org' community. I was curious about the X.org Endless Vacation of Code. Is this program still active? > > ^ permalink raw reply [flat|nested] 42+ messages in thread
* (no subject) @ 2022-04-06 7:51 Christian König 2022-04-06 12:59 ` Daniel Vetter 0 siblings, 1 reply; 42+ messages in thread From: Christian König @ 2022-04-06 7:51 UTC (permalink / raw) To: daniel.vetter, dri-devel Hi Daniel, rebased on top of all the changes in drm-misc-next now and hopefully ready for 5.19. I think I addressed all concern, but there was a bunch of rebase fallout from i915, so better to double check that once more. Regards, Christian. ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2022-04-06 7:51 Christian König @ 2022-04-06 12:59 ` Daniel Vetter 0 siblings, 0 replies; 42+ messages in thread From: Daniel Vetter @ 2022-04-06 12:59 UTC (permalink / raw) To: DMA-resvusage; +Cc: daniel.vetter, dri-devel On Wed, Apr 06, 2022 at 09:51:16AM +0200, Christian König wrote: > Hi Daniel, > > rebased on top of all the changes in drm-misc-next now and hopefully > ready for 5.19. > > I think I addressed all concern, but there was a bunch of rebase fallout > from i915, so better to double check that once more. No idea what you managed to do with this series, but - cover letter isn't showing up in archives - you have Reply-To: DMA-resvusage sprinkled all over, which means my replies are bouncing in funny ways Please fix for next time around. Also the split up patches lack a bit cc. -Daniel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ^ permalink raw reply [flat|nested] 42+ messages in thread
* (no subject) @ 2022-05-19 9:54 Christian König 2022-05-19 10:50 ` Matthew Auld 0 siblings, 1 reply; 42+ messages in thread From: Christian König @ 2022-05-19 9:54 UTC (permalink / raw) To: intel-gfx; +Cc: matthew.william.auld, dri-devel Just sending that out once more to intel-gfx to let the CI systems take a look. No functional change compared to the last version. Christian. ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2022-05-19 9:54 Christian König @ 2022-05-19 10:50 ` Matthew Auld 2022-05-20 7:11 ` Re: Christian König 0 siblings, 1 reply; 42+ messages in thread From: Matthew Auld @ 2022-05-19 10:50 UTC (permalink / raw) To: Christian König; +Cc: Intel Graphics Development, ML dri-devel On Thu, 19 May 2022 at 10:55, Christian König <ckoenig.leichtzumerken@gmail.com> wrote: > > Just sending that out once more to intel-gfx to let the CI systems take > a look. If all went well it should normally appear at [1][2], if CI was able to pick up the series. Since it's not currently there, I assume it's temporarily stuck in the moderation queue, assuming you are not subscribed to intel-gfx ml? If so, perhaps consider subscribing at [3] and then disable receiving any mail from the ml, so you get full use of CI without getting spammed. [1] https://intel-gfx-ci.01.org/queue/index.html [2] https://patchwork.freedesktop.org/project/intel-gfx/series/ [3] https://lists.freedesktop.org/mailman/listinfo/intel-gfx > > No functional change compared to the last version. > > Christian. > > ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2022-05-19 10:50 ` Matthew Auld @ 2022-05-20 7:11 ` Christian König 0 siblings, 0 replies; 42+ messages in thread From: Christian König @ 2022-05-20 7:11 UTC (permalink / raw) To: Matthew Auld; +Cc: Intel Graphics Development, ML dri-devel Am 19.05.22 um 12:50 schrieb Matthew Auld: > On Thu, 19 May 2022 at 10:55, Christian König > <ckoenig.leichtzumerken@gmail.com> wrote: >> Just sending that out once more to intel-gfx to let the CI systems take >> a look. > If all went well it should normally appear at [1][2], if CI was able > to pick up the series. > > Since it's not currently there, I assume it's temporarily stuck in the > moderation queue, assuming you are not subscribed to intel-gfx ml? Ah! Well I am subscribed, just not with the e-Mail address I use to send out those patches. Going to fix that ASAP! Thanks, Christian. > If > so, perhaps consider subscribing at [3] and then disable receiving any > mail from the ml, so you get full use of CI without getting spammed. > > [1] https://intel-gfx-ci.01.org/queue/index.html > [2] https://patchwork.freedesktop.org/project/intel-gfx/series/ > [3] https://lists.freedesktop.org/mailman/listinfo/intel-gfx > >> No functional change compared to the last version. >> >> Christian. >> >> ^ permalink raw reply [flat|nested] 42+ messages in thread
* (no subject) @ 2023-11-11 4:21 Andrew Worsley 2023-11-11 8:22 ` Javier Martinez Canillas 0 siblings, 1 reply; 42+ messages in thread From: Andrew Worsley @ 2023-11-11 4:21 UTC (permalink / raw) To: Thomas Zimmermann, Javier Martinez Canillas, Maarten Lankhorst, Maxime Ripard, David Airlie, Daniel Vetter, open list:DRM DRIVER FOR FIRMWARE FRAMEBUFFERS, open list This patch fix's the failure of the frame buffer driver on my Asahi kernel which prevented X11 from starting on my Apple M1 laptop. It seems like a straight forward failure to follow the procedure described in drivers/video/aperture.c to remove the ealier driver. This patch is very simple and minimal. Very likely there may be better ways to fix this and very like there may be other drivers which have the same problem but I submit this so at least there is an interim fix for my problem. Thanks Andrew Worsley ^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: 2023-11-11 4:21 Andrew Worsley @ 2023-11-11 8:22 ` Javier Martinez Canillas 0 siblings, 0 replies; 42+ messages in thread From: Javier Martinez Canillas @ 2023-11-11 8:22 UTC (permalink / raw) To: Andrew Worsley, Thomas Zimmermann, Maarten Lankhorst, Maxime Ripard, David Airlie, Daniel Vetter, open list:DRM DRIVER FOR FIRMWARE FRAMEBUFFERS, open list Andrew Worsley <amworsley@gmail.com> writes: Hello Andrew, > This patch fix's the failure of the frame buffer driver on my Asahi kernel > which prevented X11 from starting on my Apple M1 laptop. It seems like a straight > forward failure to follow the procedure described in drivers/video/aperture.c > to remove the ealier driver. This patch is very simple and minimal. Very likely > there may be better ways to fix this and very like there may be other drivers > which have the same problem but I submit this so at least there is > an interim fix for my problem. > Which partch? I think you forgot to include in your email? > Thanks > > Andrew Worsley > -- Best regards, Javier Martinez Canillas Core Platforms Red Hat ^ permalink raw reply [flat|nested] 42+ messages in thread
end of thread, other threads:[~2023-11-11 8:23 UTC | newest] Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-05-18 12:27 (unknown), Sascha Hauer 2012-05-18 12:27 ` [PATCH 1/2] DRM: add Freescale i.MX LCDC driver Sascha Hauer 2012-05-22 21:28 ` Rob Clark 2012-05-23 7:47 ` Sascha Hauer 2012-05-23 8:37 ` Lars-Peter Clausen 2012-05-23 9:09 ` Daniel Vetter 2012-05-18 12:27 ` [PATCH 2/2] pcm038 lcdc support Sascha Hauer 2012-05-18 14:03 ` Adam Jackson 2012-05-18 15:13 ` Sascha Hauer 2012-05-22 10:02 ` Dave Airlie 2012-05-22 14:06 ` Lars-Peter Clausen 2012-05-23 8:12 ` Re: Sascha Hauer 2012-05-24 6:31 ` Re: Sascha Hauer 2013-08-13 9:56 (unknown), Christian König 2013-08-13 14:47 ` Alex Deucher 2014-08-24 13:14 (unknown), Christian König 2014-08-24 13:34 ` Mike Lothian 2014-08-25 9:10 ` Re: Christian König 2014-09-07 13:24 ` Re: Markus Trippelsdorf 2014-09-08 3:47 ` Re: Alex Deucher 2014-09-08 7:13 ` Re: Markus Trippelsdorf 2018-03-05 17:06 (unknown) Meghana Madhyastha 2018-03-05 19:24 ` Noralf Trønnes 2018-10-21 16:25 (unknown), Michael Tirado 2018-10-22 0:26 ` Dave Airlie 2018-10-21 20:23 ` Re: Michael Tirado 2018-10-22 1:50 ` Re: Dave Airlie 2018-10-21 22:20 ` Re: Michael Tirado 2018-10-23 1:47 ` Re: Michael Tirado 2018-10-23 6:23 ` Re: Dave Airlie [not found] <86d0ec$ae4ffc@fmsmga001.fm.intel.com> 2020-02-26 12:08 ` Re: Linus Walleij 2020-02-26 14:34 ` Re: Ville Syrjälä 2020-02-26 14:56 ` Re: Linus Walleij 2020-02-26 15:08 ` Re: Ville Syrjälä 2020-09-15 2:40 Dave Airlie 2020-09-15 7:53 ` Christian König [not found] <20201008181606.460499-1-sandy.8925@gmail.com> 2020-10-09 6:47 ` Re: Thomas Zimmermann 2020-10-09 7:14 ` Re: Thomas Zimmermann 2020-10-09 7:38 ` Re: Sandeep Raghuraman 2020-10-09 7:51 ` Re: Thomas Zimmermann 2020-10-09 15:48 ` Re: Alex Deucher 2021-05-15 22:57 Dmitry Baryshkov 2021-06-02 21:45 ` Dmitry Baryshkov [not found] <CAGsV3ysM+p_HAq+LgOe4db09e+zRtvELHUQzCjF8FVE2UF+3Ow@mail.gmail.com> 2021-06-29 13:52 ` Re: Alex Deucher 2022-04-06 7:51 Christian König 2022-04-06 12:59 ` Daniel Vetter 2022-05-19 9:54 Christian König 2022-05-19 10:50 ` Matthew Auld 2022-05-20 7:11 ` Re: Christian König 2023-11-11 4:21 Andrew Worsley 2023-11-11 8:22 ` Javier Martinez Canillas
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).