[Intel-gfx] [PATCH] drm/i915: Resume DP MST before doing any kind of modesetting
On 3/1/2016 5:03 AM, Rob Clark wrote: > On Mon, Feb 29, 2016 at 11:12 AM, Daniel Vetter wrote: >> On Wed, Feb 24, 2016 at 08:03:04AM +0530, Thulasimani, Sivakumar wrote: >>> >>> On 2/24/2016 3:41 AM, Lyude wrote: As it turns out, resuming DP MST is racey since we don't make sure MST is ready before we start modesetting, it just usually happens to be ready in time. This isn't the case on all systems, particularly a ThinkPad T560 with displays connected through the dock. On these systems, resuming the laptop while connected to the dock usually results in blank monitors. Making sure MST is ready before doing any kind of modesetting fixes this issue. >>> basic question since i haven't worked on MST much. MST should work like any >>> other digital panel on resume. i.e detect followed by modeset. in the >>> modified >>> commit mentioned below is it failing to detect the panel or failing at the >>> modeset ? >>> if we are depending on the intel_display_resume, how about moving the >>> intel_dp_mst_resume just above intel_display_resume? >>> >>> >>> Generic question to others in mail list on i915_drm_resume >>> we are doing a modeset and then doing the detect/hpd init. >>> shouldn't this be the other way round ? almost all displays >>> will pass a modeset even if display is not connected so we >>> are spending time on modeset even for displays that were >>> removed during the suspend state. if this is to simply >>> drm_state being saved and restored, >> We must restore anyway, we're not really allowed to shut down a display >> without userspace's consent. DP mst breaks this, and it's not fun really. > well, that isn't completely true.. I mean, if the user unplugs (for > example) an hdmi monitor, it isn't with userspace's consent.. > > I wonder if we could just have flag per connector, ie. > connector->no_auto_resume and just automatically send unplug events > for those to userspace (followed shortly by a plug event if it is > still connected and the normal hpd mechanism kicks in? I mean, for > all we know, the user unplugged the DP monitor/hub/etc and plugged in > a different one while we were suspended.. > > BR, > -R i agree. performing a modeset on a display without even confirming if it is the same one when we had suspended the system will result in issues such as applying a mode that may not be supported on the new display or corruption or blankout or simply failing the modeset restore or worst case of doing modeset without a display connected. if we will not allow such a scenario during normal operation, i.e prevent incorrect modeset requests during normal functioning, why allow such a modeset during suspend-resume alone ? we can store the edid hash and if the display has the same hash post resume then we can allow mode to be restored. regards, Sivakumar >> So for hotunplug the flow should always be: >> 1. kernel notices something has changed in the output config. >> 2. kernel sends out uevent >> 3. userspace figures out what changed, and what needs to be done >> 4. userspace asks the kernel to change display configuration through >> setCrtc and Atomic ioctl calls. >> >> Irrespective of hotunplug handling, the kernel also _must_ restore the >> entire display configuration before userspace resumes. We can do that >> asynchronously (and there's plans for that), but even then we must stall >> userspace on the first KMS ioclt to keep up the illusion that a system s/r >> is transparent. >> >> In short, even if we do hpd processing before resuming the display, >> nothing will be faster - we must wait for userspace to make up its mind, >> and that can only happen once we've restored the display config. >> >> And again, mst is kinda breaking this, since and mst unplug results in a >> force-disable. Which can upset userspace and in general results in the >> need for lots of fragile error handling all over. >> We originally changed the resume order in commit e7d6f7d70829 ("drm/i915: resume MST after reading back hw state") to fix a ton of WARN_ON's after resume, but this doesn't seem to be an issue now anyhow. CC: stable at vger.kernel.org Signed-off-by: Lyude >> Wrt the patch itself: I think only in 4.6 we've actually fixed up all >> these mst WARN_ON. Cc: stable seems extremely risky on this one. Also, the >> modeset state readout for mst is still not entirely correct (it still >> relies on software state), so I'm not sure we've actually managed to shut >> up all the WARNINGs. Iirc the way to repro them is to hot-unplug something >> while suspended. In short the get_hw_state functions for mst should not >> rely on any mst software state, but instead just look at hw registers and >> dp aux registers to figure out what's going on. But not sure whether this >> will result on WARNINGs on resume, since generally the bios doesn't enable >> anything in that case. >> >> Furthermore MST still does a force-modeset when processing a
[PATCH v6 03/11] drm/hisilicon: Add crtc driver for ADE
On 2/26/2016 2:10 PM, Xinliang Liu wrote: > Add crtc funcs and helper funcs for ADE. > > v6: > - Cleanup reg-names dt parsing. > v5: > - Use syscon to access ADE media NOC QoS registers instread of directly >writing registers. > - Use reset controller to reset ADE instead of directly writing registers. > v4: None. > v3: > - Make ade as the master driver. > - Use port to connect with encoder. > - A few cleanup. > v2: > - Remove abtraction layer. > > Signed-off-by: Xinliang Liu > --- > drivers/gpu/drm/hisilicon/kirin/Makefile| 3 +- > drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h | 290 +++ > drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 452 > > drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 15 + > drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h | 8 + > 5 files changed, 767 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h > create mode 100644 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > > diff --git a/drivers/gpu/drm/hisilicon/kirin/Makefile > b/drivers/gpu/drm/hisilicon/kirin/Makefile > index cb346de47d48..2a61ab006ddb 100644 > --- a/drivers/gpu/drm/hisilicon/kirin/Makefile > +++ b/drivers/gpu/drm/hisilicon/kirin/Makefile > @@ -1,3 +1,4 @@ > -kirin-drm-y := kirin_drm_drv.o > +kirin-drm-y := kirin_drm_drv.o \ > +kirin_drm_ade.o > > obj-$(CONFIG_DRM_HISI_KIRIN) += kirin-drm.o > diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h > b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h > new file mode 100644 > index ..eb444b899c7b > --- /dev/null > +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h > @@ -0,0 +1,290 @@ > +/* > + * Copyright (c) 2016 Linaro Limited. > + * Copyright (c) 2014-2016 Hisilicon Limited. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + */ > + > +#ifndef __KIRIN_ADE_REG_H__ > +#define __KIRIN_ADE_REG_H__ > + > +/* > + * ADE Registers > + */ > +#define MASK(x) (BIT(x) - 1) > + > +#define ADE_CTRL 0x0004 > +#define FRM_END_START_OFST 0 > +#define FRM_END_START_MASK MASK(2) > +#define ADE_CTRL10x008C > +#define AUTO_CLK_GATE_EN_OFST0 > +#define AUTO_CLK_GATE_EN BIT(0) > +#define ADE_ROT_SRC_CFG 0x0010 > +#define ADE_DISP_SRC_CFG 0x0018 > +#define ADE_WDMA2_SRC_CFG0x001C > +#define ADE_SEC_OVLY_SRC_CFG 0x0020 > +#define ADE_WDMA3_SRC_CFG0x0024 > +#define ADE_OVLY1_TRANS_CFG 0x002C > +#define ADE_EN 0x0100 > +#define ADE_DISABLE 0 > +#define ADE_ENABLE 1 > +#define INTR_MASK_CPU(x) (0x0C10 + (x) * 0x4) > +#define ADE_FRM_DISGARD_CTRL 0x00A4 > +/* reset and reload regs */ > +#define ADE_SOFT_RST_SEL(x) (0x0078 + (x) * 0x4) > +#define ADE_RELOAD_DIS(x)(0x00AC + (x) * 0x4) > +#define RDMA_OFST0 > +#define CLIP_OFST15 > +#define SCL_OFST 21 > +#define CTRAN_OFST 24 > +#define OVLY_OFST37 /* 32+5 */ > +/* channel regs */ > +#define RD_CH_PE(x) (0x1000 + (x) * 0x80) > +#define RD_CH_CTRL(x)(0x1004 + (x) * 0x80) > +#define RD_CH_ADDR(x)(0x1008 + (x) * 0x80) > +#define RD_CH_SIZE(x)(0x100C + (x) * 0x80) > +#define RD_CH_STRIDE(x) (0x1010 + (x) * 0x80) > +#define RD_CH_SPACE(x) (0x1014 + (x) * 0x80) > +#define RD_CH_PARTIAL_SIZE(x)(0x1018 + (x) * 0x80) > +#define RD_CH_PARTIAL_SPACE(x) (0x101C + (x) * 0x80) > +#define RD_CH_EN(x) (0x1020 + (x) * 0x80) > +#define RD_CH_STATUS(x) (0x1024 + (x) * 0x80) > +#define RD_CH_DISP_CTRL 0x1404 > +#define RD_CH_DISP_ADDR 0x1408 > +#define RD_CH_DISP_SIZE 0x140C > +#define RD_CH_DISP_STRIDE0x1410 > +#define RD_CH_DISP_SPACE 0x1414 > +#define RD_CH_DISP_EN0x142C > +/* clip regs */ > +#define ADE_CLIP_DISABLE(x) (0x6800 + (x) * 0x100) > +#define ADE_CLIP_SIZE0(x)(0x6804 + (x) * 0x100) > +#define ADE_CLIP_SIZE1(x)(0x6808 + (x) * 0x100) > +#define ADE_CLIP_SIZE2(x)(0x680C + (x) * 0x100) > +#define ADE_CLIP_CFG_OK(x) (0x6810 + (x) * 0x100) > +/* scale regs */ > +#define ADE_SCL1_MUX_CFG 0x000C > +#define ADE_SCL2_SRC_CFG 0x0014 > +#define ADE_SCL3_MUX_CFG 0x0008 > +#define ADE_SCL_CTRL(x) (0x3000 + (x) * 0x800) > +#define ADE_SCL_HSP(x)
[PATCH v6 04/11] drm/hisilicon: Add plane driver for ADE
On 2/26/2016 2:10 PM, Xinliang Liu wrote: > Add plane funcs and helper funcs for ADE. > > v6: None. > v5: None. > v4: None. > v3: > - A few cleanup. > v2: > - Remove abtraction layer. > > Signed-off-by: Xinliang Liu > --- > drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 535 > +++- > 1 file changed, 534 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > index bb93616dcf3d..aa2cf75cab39 100644 > --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > @@ -27,13 +27,23 @@ > #include > #include > #include > +#include > +#include > +#include > > #include "kirin_drm_drv.h" > #include "kirin_ade_reg.h" > > +#define PRIMARY_CH ADE_CH1 /* primary plane */ > +#define OUT_OVLY ADE_OVLY2 /* output overlay compositor */ Could you briefly explain this overlay/channel mapping? It looks like it's something that is hard coded at the moment. Do channels map to planes, and OVLs map to crtcs? > +#define ADE_DEBUG1 > + > #define to_ade_crtc(crtc) \ > container_of(crtc, struct ade_crtc, base) > > +#define to_ade_plane(plane) \ > + container_of(plane, struct ade_plane, base) > + > struct ade_hw_ctx { > void __iomem *base; > struct regmap *noc_regmap; > @@ -52,11 +62,76 @@ struct ade_crtc { > u32 out_format; > }; > > +struct ade_plane { > + struct drm_plane base; > + void *ctx; > + u8 ch; /* channel */ > +}; > + > struct ade_data { > struct ade_crtc acrtc; > + struct ade_plane aplane[ADE_CH_NUM]; > struct ade_hw_ctx ctx; > }; > > +/* ade-format info: */ > +struct ade_format { > + u32 pixel_format; > + enum ade_fb_format ade_format; > +}; > + > +static const struct ade_format ade_formats[] = { > + /* 16bpp RGB: */ > + { DRM_FORMAT_RGB565, ADE_RGB_565 }, > + { DRM_FORMAT_BGR565, ADE_BGR_565 }, > + /* 24bpp RGB: */ > + { DRM_FORMAT_RGB888, ADE_RGB_888 }, > + { DRM_FORMAT_BGR888, ADE_BGR_888 }, > + /* 32bpp [A]RGB: */ > + { DRM_FORMAT_XRGB, ADE_XRGB_ }, > + { DRM_FORMAT_XBGR, ADE_XBGR_ }, > + { DRM_FORMAT_RGBA, ADE_RGBA_ }, > + { DRM_FORMAT_BGRA, ADE_BGRA_ }, > + { DRM_FORMAT_ARGB, ADE_ARGB_ }, > + { DRM_FORMAT_ABGR, ADE_ABGR_ }, > +}; > + > +static const u32 channel_formats1[] = { > + /* channel 1,2,3,4 */ > + DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888, > + DRM_FORMAT_BGR888, DRM_FORMAT_XRGB, DRM_FORMAT_XBGR, > + DRM_FORMAT_RGBA, DRM_FORMAT_BGRA, DRM_FORMAT_ARGB, > + DRM_FORMAT_ABGR > +}; > + > +u32 ade_get_channel_formats(u8 ch, const u32 **formats) > +{ > + switch (ch) { > + case ADE_CH1: > + *formats = channel_formats1; > + return ARRAY_SIZE(channel_formats1); > + default: > + DRM_ERROR("no this channel %d\n", ch); > + *formats = NULL; > + return 0; > + } > +} > + > +/* convert from fourcc format to ade format */ > +static u32 ade_get_format(u32 pixel_format) > +{ > + int i; > + > + for (i = 0; i < ARRAY_SIZE(ade_formats); i++) > + if (ade_formats[i].pixel_format == pixel_format) > + return ade_formats[i].ade_format; > + > + /* not found */ > + DRM_ERROR("Not found pixel format!!fourcc_format= %d\n", > + pixel_format); > + return ADE_FORMAT_NOT_SUPPORT; > +} > + > static void ade_update_reload_bit(void __iomem *base, u32 bit_num, u32 val) > { > u32 bit_ofst, reg_num; > @@ -89,7 +164,7 @@ static void ade_init(struct ade_hw_ctx *ctx) > /* clear overlay */ > writel(0, base + ADE_OVLY1_TRANS_CFG); > writel(0, base + ADE_OVLY_CTL); > - writel(0, base + ADE_OVLYX_CTL(ADE_OVLY2)); > + writel(0, base + ADE_OVLYX_CTL(OUT_OVLY)); > /* clear reset and reload regs */ > writel(MASK(32), base + ADE_SOFT_RST_SEL(0)); > writel(MASK(32), base + ADE_SOFT_RST_SEL(1)); > @@ -147,6 +222,10 @@ static void ade_ldi_set_mode(struct ade_crtc *acrtc, > mode->clock * 1000, ret); > adj_mode->clock = clk_get_rate(ctx->ade_pix_clk) / 1000; > > + /* set overlay compositor output size */ > + writel(((width - 1) << OUTPUT_XSIZE_OFST) | (height - 1), > +base + ADE_OVLY_OUTPUT_SIZE(OUT_OVLY)); > + > /* ctran6 setting */ > writel(CTRAN_BYPASS_ON, base + ADE_CTRAN_DIS(ADE_CTRAN6)); >/* the configured value is actual value - 1 */ > @@ -219,6 +298,10 @@ static void ade_display_enable(struct ade_crtc *acrtc) > void __iomem *base = ctx->base; > u32 out_fmt = acrtc->out_format; > > + /* enable output overlay compositor */ > + writel(ADE_ENABLE, base + ADE_OVLYX_CTL(OUT_OVLY)); > + ade_update_reload_bit(base, OVLY_OFST + OUT_OVLY, 0); > + > /* di
[PATCH v6 05/11] drm/hisilicon: Add vblank driver for ADE
On 2/26/2016 2:10 PM, Xinliang Liu wrote: > Add vblank irq handle. > > v6: None. > v5: None. > v4: None. > v3: > - Remove hisi_get_crtc_from_index func. > - A few cleanup. > v2: > - Remove abtraction layer. > > Signed-off-by: Xinliang Liu > --- > drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 62 > + > drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 14 +- > 2 files changed, 75 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > index aa2cf75cab39..749382952ab7 100644 > --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c > @@ -292,6 +292,59 @@ static void ade_set_medianoc_qos(struct ade_crtc *acrtc) > SOCKET_QOS_EN, SOCKET_QOS_EN); > } > > +static int ade_enable_vblank(struct drm_device *dev, unsigned int pipe) > +{ > + struct kirin_drm_private *priv = dev->dev_private; > + struct ade_crtc *acrtc = to_ade_crtc(priv->crtc[pipe]); > + struct ade_hw_ctx *ctx = acrtc->ctx; > + void __iomem *base = ctx->base; > + > + if (!ctx->power_on) > + (void)ade_power_up(ctx); > + > + ade_update_bits(base + LDI_INT_EN, FRAME_END_INT_EN_OFST, > + MASK(1), 1); > + > + return 0; > +} > + > +static void ade_disable_vblank(struct drm_device *dev, unsigned int pipe) > +{ > + struct kirin_drm_private *priv = dev->dev_private; > + struct ade_crtc *acrtc = to_ade_crtc(priv->crtc[pipe]); > + struct ade_hw_ctx *ctx = acrtc->ctx; > + void __iomem *base = ctx->base; > + > + if (!ctx->power_on) { > + DRM_ERROR("power is down! vblank disable fail\n"); > + return; > + } > + > + ade_update_bits(base + LDI_INT_EN, FRAME_END_INT_EN_OFST, > + MASK(1), 0); > +} > + > +static irqreturn_t ade_irq_handler(int irq, void *data) > +{ > + struct ade_crtc *acrtc = data; > + struct ade_hw_ctx *ctx = acrtc->ctx; > + struct drm_crtc *crtc = &acrtc->base; > + void __iomem *base = ctx->base; > + u32 status; > + > + status = readl(base + LDI_MSK_INT); > + DRM_DEBUG_VBL("LDI IRQ: status=0x%X\n", status); > + > + /* vblank irq */ > + if (status & BIT(FRAME_END_INT_EN_OFST)) { > + ade_update_bits(base + LDI_INT_CLR, FRAME_END_INT_EN_OFST, > + MASK(1), 1); > + drm_crtc_handle_vblank(crtc); > + } > + > + return IRQ_HANDLED; > +} > + > static void ade_display_enable(struct ade_crtc *acrtc) > { > struct ade_hw_ctx *ctx = acrtc->ctx; > @@ -967,6 +1020,15 @@ int ade_drm_init(struct drm_device *dev) > if (ret) > return ret; > > + /* vblank irq init */ > + ret = devm_request_irq(dev->dev, ctx->irq, ade_irq_handler, > +DRIVER_IRQ_SHARED, dev->driver->name, acrtc); This isn't the way we set up interrupts for kms drivers. We need to provide the handler in drm_driver and call drm_irq_install. > + if (ret) > + return ret; > + dev->driver->get_vblank_counter = drm_vblank_no_hw_counter; > + dev->driver->enable_vblank = ade_enable_vblank; > + dev->driver->disable_vblank = ade_disable_vblank; > + > return 0; > } > > diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c > b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c > index 055729c1889c..723888feb760 100644 > --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c > +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c > @@ -32,6 +32,7 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev) > { > struct kirin_drm_private *priv = dev->dev_private; > > + drm_vblank_cleanup(dev); > dc_ops->cleanup(dev); > drm_mode_config_cleanup(dev); > devm_kfree(dev->dev, priv); > @@ -85,11 +86,22 @@ static int kirin_drm_kms_init(struct drm_device *dev) > goto err_dc_cleanup; > } > > + /* vblank init */ > + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); > + if (ret) { > + DRM_ERROR("failed to initialize vblank.\n"); > + goto err_unbind_all; > + } > + /* with irq_enabled = true, we can use the vblank feature. */ > + dev->irq_enabled = true; > + > /* reset all the states of crtc/plane/encoder/connector */ > drm_mode_config_reset(dev); > > return 0; > > +err_unbind_all: > + component_unbind_all(dev->dev, dev); > err_dc_cleanup: > dc_ops->cleanup(dev); > err_mode_config_cleanup: > @@ -123,7 +135,7 @@ static int kirin_gem_cma_dumb_create(struct drm_file > *file, > > static struct drm_driver kirin_drm_driver = { > .driver_features= DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | > - DRIVER_ATOMIC, > + DRIVER_ATOMIC | DRIVER_HAVE_IRQ, DRIVER_IRQ_SHARED should be added here if you want
[PATCH v6 07/11] drm/hisilicon: Add designware dsi encoder driver
On 2/26/2016 2:10 PM, Xinliang Liu wrote: > Add DesignWare MIPI DSI Host Controller v1.02 encoder driver > for hi6220 SoC. > > v6: > - Change "pclk_dsi" to "pclk". > v5: None. > v4: None. > v3: > - Rename file name to dw_drm_dsi.c > - Make encoder type as DRM_MODE_ENCODER_DSI. > - A few cleanup. > v2: > - Remove abtraction layer. > > Signed-off-by: Xinliang Liu > Signed-off-by: Xinwei Kong > Signed-off-by: Andy Green > --- > drivers/gpu/drm/hisilicon/kirin/Kconfig | 1 + > drivers/gpu/drm/hisilicon/kirin/Makefile | 3 +- > drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 743 > +++ > drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h | 83 +++ > 4 files changed, 829 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > create mode 100644 drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h > > diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig > b/drivers/gpu/drm/hisilicon/kirin/Kconfig > index 3ac4b8edeac1..de0d454c5c13 100644 > --- a/drivers/gpu/drm/hisilicon/kirin/Kconfig > +++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig > @@ -4,6 +4,7 @@ config DRM_HISI_KIRIN > select DRM_KMS_HELPER > select DRM_GEM_CMA_HELPER > select DRM_KMS_CMA_HELPER > + select DRM_MIPI_DSI > help > Choose this option if you have a hisilicon Kirin chipsets(hi6220). > If M is selected the module will be called kirin-drm. > diff --git a/drivers/gpu/drm/hisilicon/kirin/Makefile > b/drivers/gpu/drm/hisilicon/kirin/Makefile > index 2a61ab006ddb..5dcd0d4328b6 100644 > --- a/drivers/gpu/drm/hisilicon/kirin/Makefile > +++ b/drivers/gpu/drm/hisilicon/kirin/Makefile > @@ -1,4 +1,5 @@ > kirin-drm-y := kirin_drm_drv.o \ > -kirin_drm_ade.o > +kirin_drm_ade.o \ > +dw_drm_dsi.o > > obj-$(CONFIG_DRM_HISI_KIRIN) += kirin-drm.o > diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > new file mode 100644 > index ..8329148cc89d > --- /dev/null > +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > @@ -0,0 +1,743 @@ > +/* > + * DesignWare MIPI DSI Host Controller v1.02 driver > + * > + * Copyright (c) 2016 Linaro Limited. > + * Copyright (c) 2014-2016 Hisilicon Limited. > + * > + * Author: > + * Xinliang Liu > + * Xinliang Liu > + * Xinwei Kong > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + */ > + > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include "dw_dsi_reg.h" > + > +#define MAX_TX_ESC_CLK (10) > +#define ROUND(x, y) ((x) / (y) + ((x) % (y) * 10 / (y) >= 5 ? 1 : 0)) > +#define PHY_REF_CLK_RATE 1920 > +#define PHY_REF_CLK_PERIOD_PS (10 / (PHY_REF_CLK_RATE / 1000)) > + > +#define encoder_to_dsi(encoder) \ > + container_of(encoder, struct dw_dsi, encoder) > +#define host_to_dsi(host) \ > + container_of(host, struct dw_dsi, host) > + > +struct mipi_phy_params { > + u32 clk_t_lpx; > + u32 clk_t_hs_prepare; > + u32 clk_t_hs_zero; > + u32 clk_t_hs_trial; > + u32 clk_t_wakeup; > + u32 data_t_lpx; > + u32 data_t_hs_prepare; > + u32 data_t_hs_zero; > + u32 data_t_hs_trial; > + u32 data_t_ta_go; > + u32 data_t_ta_get; > + u32 data_t_wakeup; > + u32 hstx_ckg_sel; > + u32 pll_fbd_div5f; > + u32 pll_fbd_div1f; > + u32 pll_fbd_2p; > + u32 pll_enbwt; > + u32 pll_fbd_p; > + u32 pll_fbd_s; > + u32 pll_pre_div1p; > + u32 pll_pre_p; > + u32 pll_vco_750M; > + u32 pll_lpf_rs; > + u32 pll_lpf_cs; > + u32 clklp2hs_time; > + u32 clkhs2lp_time; > + u32 lp2hs_time; > + u32 hs2lp_time; > + u32 clk_to_data_delay; > + u32 data_to_clk_delay; > + u32 lane_byte_clk_kHz; > + u32 clk_division; > +}; > + > +struct dsi_hw_ctx { > + void __iomem *base; > + struct clk *pclk; > +}; > + > +struct dw_dsi { > + struct drm_encoder encoder; > + struct drm_display_mode cur_mode; > + struct dsi_hw_ctx *ctx; > + struct mipi_phy_params phy; > + > + u32 lanes; > + enum mipi_dsi_pixel_format format; > + unsigned long mode_flags; > + bool enable; > +}; > + > +struct dsi_data { > + struct dw_dsi dsi; > + struct dsi_hw_ctx ctx; > +}; > + > +struct dsi_phy_range { > + u32 min_range_kHz; > + u32 max_range_kHz; > + u32 pll_vco_750M; > + u32 hstx_ckg_sel; > +}; > + > +static const struct dsi_phy_range dphy_range_info[] = { > + { 46875,62500, 1,7 }, > + { 62500,93750, 0,7 }, > + { 93750, 125000, 1,6 }, > + { 125000, 187500, 0,6 }, > + { 187500, 25, 1,5 }, > + { 25, 375000, 0,5 }, > + { 375000, 50, 1,4
[PATCH v6 08/11] drm/hisilicon: Add designware dsi host driver
On 2/26/2016 2:10 PM, Xinliang Liu wrote: > Add DesignWare dsi host driver for hi6220 SoC. > > v6: None. > v5: None. > v4: None. > v3: None. > v2: > - Remove abtraction layer. Reviewed-by: Archit Taneja > > Signed-off-by: Xinliang Liu > --- > drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 50 > > 1 file changed, 50 insertions(+) > > diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > index 8329148cc89d..f15798b61451 100644 > --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > @@ -79,6 +79,7 @@ struct dsi_hw_ctx { > > struct dw_dsi { > struct drm_encoder encoder; > + struct mipi_dsi_host host; > struct drm_display_mode cur_mode; > struct dsi_hw_ctx *ctx; > struct mipi_phy_params phy; > @@ -642,6 +643,51 @@ static int dw_drm_encoder_init(struct device *dev, > return 0; > } > > +static int dsi_host_attach(struct mipi_dsi_host *host, > +struct mipi_dsi_device *mdsi) > +{ > + struct dw_dsi *dsi = host_to_dsi(host); > + > + if (mdsi->lanes < 1 || mdsi->lanes > 4) { > + DRM_ERROR("dsi device params invalid\n"); > + return -EINVAL; > + } > + > + dsi->lanes = mdsi->lanes; > + dsi->format = mdsi->format; > + dsi->mode_flags = mdsi->mode_flags; > + > + return 0; > +} > + > +static int dsi_host_detach(struct mipi_dsi_host *host, > +struct mipi_dsi_device *mdsi) > +{ > + /* do nothing */ > + return 0; > +} > + > +static const struct mipi_dsi_host_ops dsi_host_ops = { > + .attach = dsi_host_attach, > + .detach = dsi_host_detach, > +}; > + > +static int dsi_host_init(struct device *dev, struct dw_dsi *dsi) > +{ > + struct mipi_dsi_host *host = &dsi->host; > + int ret; > + > + host->dev = dev; > + host->ops = &dsi_host_ops; > + ret = mipi_dsi_host_register(host); > + if (ret) { > + DRM_ERROR("failed to register dsi host\n"); > + return ret; > + } > + > + return 0; > +} > + > static int dsi_bind(struct device *dev, struct device *master, void *data) > { > struct dsi_data *ddata = dev_get_drvdata(dev); > @@ -653,6 +699,10 @@ static int dsi_bind(struct device *dev, struct device > *master, void *data) > if (ret) > return ret; > > + ret = dsi_host_init(dev, dsi); > + if (ret) > + return ret; > + > return 0; > } > > -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v6 09/11] drm/hisilicon: Add support for external bridge
On 2/26/2016 2:10 PM, Xinliang Liu wrote: > Add support for external HDMI bridge. > > v6: None. > v5: None. > v4: None. > v3: > - Fix a typo: s/exteranl/external. > v2: > - Remove abtraction layer. > Reviewed-by: Archit Taneja > Signed-off-by: Xinliang Liu > --- > drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 52 > > 1 file changed, 52 insertions(+) > > diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > index f15798b61451..c2c406446513 100644 > --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c > @@ -79,6 +79,7 @@ struct dsi_hw_ctx { > > struct dw_dsi { > struct drm_encoder encoder; > + struct drm_bridge *bridge; > struct mipi_dsi_host host; > struct drm_display_mode cur_mode; > struct dsi_hw_ctx *ctx; > @@ -688,6 +689,25 @@ static int dsi_host_init(struct device *dev, struct > dw_dsi *dsi) > return 0; > } > > +static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi) > +{ > + struct drm_encoder *encoder = &dsi->encoder; > + struct drm_bridge *bridge = dsi->bridge; > + int ret; > + > + /* associate the bridge to dsi encoder */ > + encoder->bridge = bridge; > + bridge->encoder = encoder; > + > + ret = drm_bridge_attach(dev, bridge); > + if (ret) { > + DRM_ERROR("failed to attach external bridge\n"); > + return ret; > + } > + > + return 0; > +} > + > static int dsi_bind(struct device *dev, struct device *master, void *data) > { > struct dsi_data *ddata = dev_get_drvdata(dev); > @@ -703,6 +723,10 @@ static int dsi_bind(struct device *dev, struct device > *master, void *data) > if (ret) > return ret; > > + ret = dsi_bridge_init(drm_dev, dsi); > + if (ret) > + return ret; > + > return 0; > } > > @@ -719,8 +743,36 @@ static const struct component_ops dsi_ops = { > static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi *dsi) > { > struct dsi_hw_ctx *ctx = dsi->ctx; > + struct device_node *np = pdev->dev.of_node; > + struct device_node *endpoint, *bridge_node; > + struct drm_bridge *bridge; > struct resource *res; > > + /* > + * Get the endpoint node. In our case, dsi has one output port1 > + * to which the external HDMI bridge is connected. > + */ > + endpoint = of_graph_get_endpoint_by_regs(np, 1, -1); > + if (!endpoint) { > + DRM_ERROR("no valid endpoint node\n"); > + return -ENODEV; > + } > + of_node_put(endpoint); > + > + bridge_node = of_graph_get_remote_port_parent(endpoint); > + if (!bridge_node) { > + DRM_ERROR("no valid bridge node\n"); > + return -ENODEV; > + } > + of_node_put(bridge_node); > + > + bridge = of_drm_find_bridge(bridge_node); > + if (!bridge) { > + DRM_INFO("wait for external HDMI bridge driver.\n"); > + return -EPROBE_DEFER; > + } > + dsi->bridge = bridge; > + > ctx->pclk = devm_clk_get(&pdev->dev, "pclk"); > if (IS_ERR(ctx->pclk)) { > DRM_ERROR("failed to get pclk clock\n"); > -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
[Intel-gfx] [PATCH] drm/i915: Resume DP MST before doing any kind of modesetting
On 1 March 2016 at 02:12, Daniel Vetter wrote: > On Wed, Feb 24, 2016 at 08:03:04AM +0530, Thulasimani, Sivakumar wrote: >> >> >> On 2/24/2016 3:41 AM, Lyude wrote: >> >As it turns out, resuming DP MST is racey since we don't make sure MST >> >is ready before we start modesetting, it just usually happens to be >> >ready in time. This isn't the case on all systems, particularly a >> >ThinkPad T560 with displays connected through the dock. On these >> >systems, resuming the laptop while connected to the dock usually results >> >in blank monitors. Making sure MST is ready before doing any kind of >> >modesetting fixes this issue. >> basic question since i haven't worked on MST much. MST should work like any >> other digital panel on resume. i.e detect followed by modeset. in the >> modified >> commit mentioned below is it failing to detect the panel or failing at the >> modeset ? >> if we are depending on the intel_display_resume, how about moving the >> intel_dp_mst_resume just above intel_display_resume? >> >> >> Generic question to others in mail list on i915_drm_resume >> we are doing a modeset and then doing the detect/hpd init. >> shouldn't this be the other way round ? almost all displays >> will pass a modeset even if display is not connected so we >> are spending time on modeset even for displays that were >> removed during the suspend state. if this is to simply >> drm_state being saved and restored, > > We must restore anyway, we're not really allowed to shut down a display > without userspace's consent. DP mst breaks this, and it's not fun really. > So for hotunplug the flow should always be: > 1. kernel notices something has changed in the output config. > 2. kernel sends out uevent > 3. userspace figures out what changed, and what needs to be done > 4. userspace asks the kernel to change display configuration through > setCrtc and Atomic ioctl calls. > > Irrespective of hotunplug handling, the kernel also _must_ restore the > entire display configuration before userspace resumes. We can do that > asynchronously (and there's plans for that), but even then we must stall > userspace on the first KMS ioclt to keep up the illusion that a system s/r > is transparent. > > In short, even if we do hpd processing before resuming the display, > nothing will be faster - we must wait for userspace to make up its mind, > and that can only happen once we've restored the display config. > > And again, mst is kinda breaking this, since and mst unplug results in a > force-disable. Which can upset userspace and in general results in the > need for lots of fragile error handling all over. > >> >We originally changed the resume order in >> > >> > commit e7d6f7d70829 ("drm/i915: resume MST after reading back hw >> > state") >> > >> >to fix a ton of WARN_ON's after resume, but this doesn't seem to be an >> >issue now anyhow. >> > >> >CC: stable at vger.kernel.org >> >Signed-off-by: Lyude > > Wrt the patch itself: I think only in 4.6 we've actually fixed up all > these mst WARN_ON. Cc: stable seems extremely risky on this one. Also, the > modeset state readout for mst is still not entirely correct (it still > relies on software state), so I'm not sure we've actually managed to shut > up all the WARNINGs. Iirc the way to repro them is to hot-unplug something > while suspended. In short the get_hw_state functions for mst should not > rely on any mst software state, but instead just look at hw registers and > dp aux registers to figure out what's going on. But not sure whether this > will result on WARNINGs on resume, since generally the bios doesn't enable > anything in that case. > > Furthermore MST still does a force-modeset when processing a hotunplug. > Doing that before we've resumed the display is likely a very bad idea. > What we need to fix that part is to separate the dp mst connector > hotplug/unplugging from actually updating the modeset change. This needs > reference-counting on drm_connector (so that we can lazily free > drm_connector structs after hot-unplug), and is a major change. I agree on the dropping stable on this, just put it in 4.6 for now, actually I'm happy to send in for 4.5 at this stage as it fixes some laptops I have as well. However I'm not sure how you think we can keep hw state programmed when the hw is gone away until userspace comes along to do something about it, the hw state is mostly on the other side of the MST link which has also gone away. My experience with leaving the crtcs programmed was and I might not be 100% sure was hw hangs, I even managed to get some MCEs over time. Though I might be tempted to go investigate this a bit more. Dave.
[PATCH v4 1/5] staging/android: add num_fences field to struct sync_file_info
This breaks userspace. You used to be able to figure it out from info->len - sizeof(struct sync_file_info). regards, dan carpenter
[PATCH v4 4/5] staging/android: refactor SYNC_IOC_FILE_INFO
On Fri, Feb 26, 2016 at 03:31:46PM -0300, Gustavo Padovan wrote: > +no_fences: > + info->num_fences = sync_file->num_fences; > > - if (copy_to_user((void __user *)arg, info, len)) > + if (copy_to_user((void __user *)arg, info, sizeof(*info))) > ret = -EFAULT; > else > ret = 0; We need to kfree(fence_info) here. > diff --git a/drivers/staging/android/uapi/sync.h > b/drivers/staging/android/uapi/sync.h > index f0b41ce..9aad623 100644 > --- a/drivers/staging/android/uapi/sync.h > +++ b/drivers/staging/android/uapi/sync.h > @@ -42,21 +42,20 @@ struct sync_fence_info { > > /** > * struct sync_file_info - data returned from fence info ioctl > - * @len: ioctl caller writes the size of the buffer its passing in. > - * ioctl returns length of sync_file_info returned to > - * userspace including pt_info. > * @name:name of fence > * @status: status of fence. 1: signaled 0:active <0:error > * @num_fences number of fences in the sync_file > + * @len: ioctl caller writes the size of the buffer its passing in. > + * ioctl returns length of all fence_infos summed. > * @sync_fence_info: array of sync_fence_info for every fence in the > sync_file The documentation needs updating. > */ > struct sync_file_info { > - __u32 len; > charname[32]; > __s32 status; > __u32 num_fences; > + __u32 len; > > - __u8sync_fence_info[0]; > + __u64 sync_fence_info; > }; regards, dan carpenter
[Bug 93826] 144Hz graphic glitches and bad refresh rate
https://bugs.freedesktop.org/show_bug.cgi?id=93826 --- Comment #20 from Damien --- Hi Alex. I understand better. Unfortunately I'm not an expert. Can you offer me a PKGBUILD Patch or tell me what value i need change in atombios.crtc.c and what to put there? -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160301/aa1d9352/attachment-0001.html>
[PATCHv2 20/31] drm/omap: HDMI: Fix HSW value
On 29/02/16 23:55, Laurent Pinchart wrote: > Hi Tomi, > > Thank you for the patch. > > On Friday 26 February 2016 11:36:08 Tomi Valkeinen wrote: >> On OMAP4 and OMAP5 ES1.0 the HDMI_WP_VIDEO_TIMING_H:HSW field is >> set directly to the HSW value. On later SoCs the field needs to be >> programmed with the value of HSW-1. >> >> Currently the driver always programs the field with the HSW value. Most >> videomodes seem to work fine with that, but at least low resolution >> interlaced modes don't work at all. >> >> This patch fixes the HSW for OMAP5 ES2.0+ SoCs. >> >> Signed-off-by: Tomi Valkeinen >> --- >> drivers/gpu/drm/omapdrm/dss/hdmi_wp.c | 14 +- >> 1 file changed, 13 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c >> b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index 7c544bc56fb5..48ffb39663c8 >> 100644 >> --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c >> +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c >> @@ -165,12 +165,24 @@ void hdmi_wp_video_config_timing(struct hdmi_wp_data >> *wp, { >> u32 timing_h = 0; >> u32 timing_v = 0; >> +bool hsw_minus_one = true; >> >> DSSDBG("Enter hdmi_wp_video_config_timing\n"); >> >> +/* >> + * On OMAP4 and OMAP5 ES1 the HSW field is programmed as is. On OMAP5 >> + * ES2+ (including DRA7/AM5 SoCs) HSW field is programmed to hsw-1. >> + * However, we don't support OMAP5 ES1 at all, so we can just check for >> + * OMAP4 here. >> + */ >> +if (omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES1 || >> +omapdss_get_version() == OMAPDSS_VER_OMAP4430_ES2 || >> +omapdss_get_version() == OMAPDSS_VER_OMAP4) >> +hsw_minus_one = false; >> + >> timing_h |= FLD_VAL(timings->hbp, 31, 20); >> timing_h |= FLD_VAL(timings->hfp, 19, 8); >> -timing_h |= FLD_VAL(timings->hsw, 7, 0); >> +timing_h |= FLD_VAL(timings->hsw - (hsw_minus_one ? 1 : 0), 7, 0); > > If you named the variable hsw_offset, make it an unsigned int, initialized it > to 1 and set it to 0 instead of false, you could write this as Thanks, that's a bit cleaner. I've made the change. Tomi -- next part -- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 819 bytes Desc: OpenPGP digital signature URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160301/db911920/attachment.sig>
[PATCH] staging/android: refactor SYNC_IOC_FILE_INFO
Op 29-02-16 om 23:08 schreef Gustavo Padovan: > Hi Maarten, > > 2016-02-29 Maarten Lankhorst : > >> Op 26-02-16 om 22:00 schreef Gustavo Padovan: >>> From: Gustavo Padovan >>> >>> Change SYNC_IOC_FILE_INFO behaviour to avoid future API breaks and >>> optimize buffer allocation. In the new approach the ioctl needs to be called >>> twice to retrieve the array of fence_infos pointed by info->sync_fence_info. >>> >>> The first call should pass num_fences = 0, the kernel will then fill >>> info->num_fences. Userspace receives back the number of fences and >>> allocates a buffer size num_fences * sizeof(struct sync_fence_info) on >>> info->sync_fence_info. >>> >>> It then call the ioctl again passing num_fences received in >>> info->num_fences. >>> The kernel checks if info->num_fences > 0 and if yes it fill >>> info->sync_fence_info with an array containing all fence_infos. >>> >>> info->len now represents the length of the buffer sync_fence_info points >>> to. Also, info->sync_fence_info was converted to __u64 pointer. >>> >>> An example userspace code would be: >>> >>> struct sync_file_info *info; >>> int err, size, num_fences; >>> >>> info = malloc(sizeof(*info)); >>> >>> memset(info, 0, sizeof(*info)); >>> >>> err = ioctl(fd, SYNC_IOC_FILE_INFO, info); >>> num_fences = info->num_fences; >>> >>> if (num_fences) { >>> memset(info, 0, sizeof(*info)); >> Would this memset still be needed if we didn't check for nulls in >> info->status and info->name ? >> >> Seems to me that it could be skipped in that case. > Yes, I agree. > >>> size = sizeof(struct sync_fence_info) * num_fences; >>> info->len = size; >>> info->num_fences = num_fences; >>> info->sync_fence_info = (uint64_t) calloc(num_fences, >>> sizeof(struct >>> sync_fence_info)); >>> >>> err = ioctl(fd, SYNC_IOC_FILE_INFO, info); >>> } >>> >>> v2: fix fence_info memory leak >>> >>> Signed-off-by: Gustavo Padovan >>> --- >>> drivers/staging/android/sync.c | 52 >>> + >>> drivers/staging/android/uapi/sync.h | 9 +++ >>> 2 files changed, 45 insertions(+), 16 deletions(-) >>> >>> diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c >>> index dc5f382..2379f23 100644 >>> --- a/drivers/staging/android/sync.c >>> +++ b/drivers/staging/android/sync.c >>> @@ -502,21 +502,22 @@ static int sync_fill_fence_info(struct fence *fence, >>> void *data, int size) >>> static long sync_file_ioctl_fence_info(struct sync_file *sync_file, >>> unsigned long arg) >>> { >>> - struct sync_file_info *info; >>> + struct sync_file_info in, *info; >>> + struct sync_fence_info *fence_info = NULL; >>> __u32 size; >>> __u32 len = 0; >> = 0 unneeded. >>> int ret, i; >>> >>> - if (copy_from_user(&size, (void __user *)arg, sizeof(size))) >>> + if (copy_from_user(&in, (void __user *)arg, sizeof(*info))) >>> return -EFAULT; >>> >>> - if (size < sizeof(struct sync_file_info)) >>> - return -EINVAL; >>> + if (in.status || strcmp(in.name, "\0")) >>> + return -EFAULT; >> These members always get written by the fence ioctl, I'm not sure it adds >> value to have them explicitly zero'd out by userspace. >>> - if (size > 4096) >>> - size = 4096; >>> + if (in.num_fences && !in.sync_fence_info) >>> + return -EFAULT; >> This check is unneeded, it will happen in the copy_to_user call anyway. >>> - info = kzalloc(size, GFP_KERNEL); >>> + info = kzalloc(sizeof(*info), GFP_KERNEL); >>> if (!info) >>> return -ENOMEM; >>> >>> @@ -525,14 +526,33 @@ static long sync_file_ioctl_fence_info(struct >>> sync_file *sync_file, >>> if (info->status >= 0) >>> info->status = !info->status; >>> >>> - info->num_fences = sync_file->num_fences; >>> + /* >>> +* Passing num_fences = 0 means that userspace want to know how >>> +* many fences are in the sync_file to be able to allocate a buffer to >>> +* fit all sync_fence_infos and call the ioctl again with the buffer >>> +* assigned to info->sync_fence_info. The second call pass the >>> +* num_fences value received in the first call. >>> +*/ >>> + if (!in.num_fences) >>> + goto no_fences; >>> + >>> + size = sync_file->num_fences * sizeof(*fence_info); >>> + if (in.len != size) { >>> + ret = -EFAULT; >>> + goto out; >>> + } >> Maybe check for in.len < size, and set set to size? >> >> >>> - len = sizeof(struct sync_file_info); >>> + fence_info = kzalloc(size, GFP_KERNEL); >>> + if (!fence_info) { >>> + ret = -ENOMEM; >>> + goto out; >>> + } >>> >>> for (i = 0; i < sync_file->num_fences; ++i) { >>> struct fence *fence = sync_file->cbs[i].fence; >>> >>> - ret = sync_fill
[PATCH] dma-buf/fence: fix fence_is_later v2
Op 29-02-16 om 23:13 schreef Gustavo Padovan: > 2016-02-29 Alex Deucher : > >> From: Christian König >> >> A fence is never later than itself. This caused a bunch of overhead for >> AMDGPU. >> >> v2: simplify check as suggested by Michel. >> >> Signed-off-by: Christian König >> Reviewed-by: Michel Dänzer >> Reviewed-by: Alex Deucher >> Signed-off-by: Alex Deucher >> --- >> include/linux/fence.h | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) > Reviewed-by: Gustavo Padovan > > Gustavo Why is it causing overhead? Not really opposed to the patch though.
[PATCH] dma-buf/fence: fix fence_is_later v2
Am 01.03.2016 um 09:36 schrieb Maarten Lankhorst: > Op 29-02-16 om 23:13 schreef Gustavo Padovan: >> 2016-02-29 Alex Deucher : >> >>> From: Christian König >>> >>> A fence is never later than itself. This caused a bunch of overhead for >>> AMDGPU. >>> >>> v2: simplify check as suggested by Michel. >>> >>> Signed-off-by: Christian König >>> Reviewed-by: Michel Dänzer >>> Reviewed-by: Alex Deucher >>> Signed-off-by: Alex Deucher >>> --- >>> include/linux/fence.h | 2 +- >>> 1 file changed, 1 insertion(+), 1 deletion(-) >> Reviewed-by: Gustavo Padovan >> >> Gustavo > Why is it causing overhead? Not really opposed to the patch though. We tested if flushing the VM is necessary by remembering the last flushed VM update operation and comparing that to what operation we need to have flushed for the current command submission to work. So when we where already at the last operation in the timeline we would flush anyway which was superfluous. Regards, Christian.
[PATCH 1/7] drm/hisilicon:Add hisilicon hibmc master driver.
Hi, Emil Thanks for reviewing this path. å¨ 2016/2/29 17:40, Emil Velikov åé: > On 29 February 2016 at 00:58, lijianhua wrote: >> Add hibmc DRM master driver for hi1710 which used in arm64 board. >> > Would be nice to give examples of what "arm64 board" this hardware is > presently available. Some information about the device as seen in the > cover letter, and/or a link to the cover letter would be nice to have. > Apply ,Will be fixed in next version.thanks! >> Signed-off-by: lijianhua >> --- >> drivers/gpu/drm/Kconfig | 2 + >> drivers/gpu/drm/Makefile| 1 + >> drivers/gpu/drm/hisilicon/Kconfig | 4 + >> drivers/gpu/drm/hisilicon/Makefile | 4 + >> drivers/gpu/drm/hisilicon/hibmc/Kconfig | 13 + >> drivers/gpu/drm/hisilicon/hibmc/Makefile| 5 + >> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 301 +++ >> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 49 +++ >> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_hw.c | 83 >> drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_hw.h | 484 >> >> 10 files changed, 946 insertions(+) >> create mode 100644 drivers/gpu/drm/hisilicon/Kconfig >> create mode 100644 drivers/gpu/drm/hisilicon/Makefile >> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Kconfig >> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/Makefile >> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c >> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h >> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_hw.c >> create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_hw.h >> >> diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig >> index 8ae7ab6..600f94d 100644 >> --- a/drivers/gpu/drm/Kconfig >> +++ b/drivers/gpu/drm/Kconfig >> @@ -269,3 +269,5 @@ source "drivers/gpu/drm/imx/Kconfig" >> source "drivers/gpu/drm/vc4/Kconfig" >> >> source "drivers/gpu/drm/etnaviv/Kconfig" >> + >> +source "drivers/gpu/drm/hisilicon/Kconfig" >> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile >> index 61766de..6055483 100644 >> --- a/drivers/gpu/drm/Makefile >> +++ b/drivers/gpu/drm/Makefile >> @@ -74,3 +74,4 @@ obj-y += panel/ >> obj-y += bridge/ >> obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/ >> obj-$(CONFIG_DRM_ETNAVIV) += etnaviv/ >> +obj-y += hisilicon/ >> diff --git a/drivers/gpu/drm/hisilicon/Kconfig >> b/drivers/gpu/drm/hisilicon/Kconfig >> new file mode 100644 >> index 000..1f10e17 >> --- /dev/null >> +++ b/drivers/gpu/drm/hisilicon/Kconfig >> @@ -0,0 +1,4 @@ >> +# hisilicon drm device configuration. >> +# Please keep this sorted alphabetically. >> + >> +source "drivers/gpu/drm/hisilicon/hibmc/Kconfig" >> diff --git a/drivers/gpu/drm/hisilicon/Makefile >> b/drivers/gpu/drm/hisilicon/Makefile >> new file mode 100644 >> index 000..487d5b0 >> --- /dev/null >> +++ b/drivers/gpu/drm/hisilicon/Makefile >> @@ -0,0 +1,4 @@ >> +# Makefile for hisilicon drm drivers. >> +# Please keep this list sorted alphabetically >> + >> +obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc/ >> \ No newline at end of file >> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig >> b/drivers/gpu/drm/hisilicon/hibmc/Kconfig >> new file mode 100644 >> index 000..c60ace6 >> --- /dev/null >> +++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig >> @@ -0,0 +1,13 @@ >> +config DRM_HISI_HIBMC >> + tristate "DRM Support for hisilicon hibmc dispi vga interface" > Use proper capitalisation in the above ? Is the driver copied/derived > from bochs - the above does not sounds right. Apply ,Will be fixed in next version.thanks! > >> + depends on DRM && PCI >> + select DRM_KMS_HELPER >> + select DRM_KMS_FB_HELPER >> + select DRM_GEM_CMA_HELPER >> + select DRM_KMS_CMA_HELPER >> + select FB_SYS_FILLRECT >> + select FB_SYS_COPYAREA >> + select FB_SYS_IMAGEBLIT >> + help >> + Choose this option for qemu. > Err what - too much copy/pasta ? Apply ,thanks! > >> + If M is selected the module will be called hibmc-drm. >> diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile >> b/drivers/gpu/drm/hisilicon/hibmc/Makefile >> new file mode 100644 >> index 000..28e59bb >> --- /dev/null >> +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile >> @@ -0,0 +1,5 @@ >> +ccflags-y := -Iinclude/drm > Based on the includes in hibmc_drm_drv.c the above include isn't needed. Apply ,thanks! > >> +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_hw.o >> + >> +obj-$(CONFIG_DRM_HISI_HIBMC) +=hibmc-drm.o >> +#obj-y += hibmc-drm.o >> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c >> b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c >> new file mode 100644 >> index 000..444ced8 >> --- /dev/null >> +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c >> @@ -0,0 +1,301 @@ >> +/* >> + * Copyright
freezes upon system boot with kernel 4.2.0-30
[1.] freezes upon system boot with kernel 4.2.0-30 [2.] This upstart job never ends: "A start job is running for Detect the available GPUs and deal with any system changes" [3.] radeon [4.] Not available. I've tested with 4.5.0-040500rc6. See kernel bisect at bottom of this email. [5.] Not available. [6.] Not available. [7.] Description:Ubuntu 15.10 Release:15.10 [7.1.] Note: Since system does not start I've done all 7.x steps with 4.2.0-27. $ sh ver_linux If some fields are empty or look unusual you may have an old version. Compare to the current minimal requirements in Documentation/Changes. Linux m-zbook 4.2.0-27-generic #32-Ubuntu SMP Fri Jan 22 04:49:08 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux Gnu C 5.2.1 Gnu make 4.0 binutils 2.25.1 util-linux 2.26.2 mount debug module-init-tools 21 e2fsprogs 1.42.12 pcmciautils018 PPP2.4.6 Linux C Library2.21 Dynamic linker (ldd) 2.21 Procps 3.3.9 Net-tools 1.60 Kbd1.15.5 Sh-utils 8.23 wireless-tools 30 Modules Loaded pci_stub vboxpci vboxnetadp vboxnetflt vboxdrv xt_conntrack ipt_MASQUERADE nf_nat_masquerade_ipv4 iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 xt_addrtype iptable_filter ip_tables x_tables nf_nat nf_conntrack br_netfilter bridge stp llc ctr ccm rfcomm aufs bnep binfmt_misc arc4 hp_wmi sparse_keymap intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm snd_hda_codec_hdmi iwlmvm snd_hda_codec_idt snd_hda_codec_generic input_leds uvcvideo mac80211 videobuf2_vmalloc videobuf2_memops snd_hda_intel videobuf2_core v4l2_common joydev videodev snd_hda_codec snd_seq_midi serio_raw media snd_seq_midi_event btusb btrtl snd_hda_core btbcm btintel snd_rawmidi snd_hwdep bluetooth iwlwifi snd_pcm rtsx_pci_ms lpc_ich memstick cfg80211 snd_seq snd_seq_device snd_timer snd mei_me mei shpchp soundcore hp_accel 8250_fintek lis3lv02d hp_wireless intel_smartconnect input_polldev mac_hid tpm_infineon nfsd auth_rpcgss nfs_acl lockd grace sunrpc parport_pc ppdev lp parport autofs4 drbg ansi_cprng algif_skcipher af_alg dm_crypt hid_generic usbhid hid rtsx_pci_sdmmc crct10dif_pclmul crc32_pclmul amdkfd aesni_intel amd_iommu_v2 radeon aes_x86_64 lrw gf128mul glue_helper ablk_helper cryptd psmouse i915 ahci libahci rtsx_pci ttm i2c_algo_bit e1000e drm_kms_helper ptp drm pps_core wmi video [7.2.] $ cat /proc/cpuinfo processor: 0 vendor_id: GenuineIntel cpu family: 6 model: 69 model name: Intel(R) Core(TM) i7-4510U CPU @ 2.00GHz stepping: 1 microcode: 0x1c cpu MHz: 800.007 cache size: 4096 KB physical id: 0 siblings: 4 core id: 0 cpu cores: 2 apicid: 0 initial apicid: 0 fpu: yes fpu_exception: yes cpuid level: 13 wp: yes flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm ida arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt bugs: bogomips: 5187.95 clflush size: 64 cache_alignment: 64 address sizes: 39 bits physical, 48 bits virtual power management: processor: 1 vendor_id: GenuineIntel cpu family: 6 model: 69 model name: Intel(R) Core(TM) i7-4510U CPU @ 2.00GHz stepping: 1 microcode: 0x1c cpu MHz: 800.007 cache size: 4096 KB physical id: 0 siblings: 4 core id: 0 cpu cores: 2 apicid: 1 initial apicid: 1 fpu: yes fpu_exception: yes cpuid level: 13 wp: yes flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 fma cx16 xtpr pdcm pcid sse4_1 sse4_2 movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm ida arat epb pln pts dtherm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid xsaveopt bugs: bogomips: 5187.95 clflush size: 64 cache_alignment: 64 address sizes: 39 bits physical, 48 bits virtual power management: processor: 2 vendor_id: GenuineIntel cpu family: 6 model: 69 model name: Intel(R) Core(TM) i7-4510U CPU @ 2.00GHz stepping: 1 microcode: 0x1c cpu MHz: 800.007 cache
[CABC PATCH 2/2] drm/i915: CABC support for backlight control
In CABC (Content Adaptive Brightness Control) content grey level scale can be increased while simultaneously decreasing brightness of the backlight to achieve same perceived brightness. The CABC is not standardized and panel vendors are free to follow their implementation. The CABC implementaion here assumes that the panels use standard SW register for control. In this design there will be no PWM signal from the SoC and DCS commands are sent to enable and control the backlight brightness. v2: Moving the CABC bkl functions to new file.(Jani) Cc: Jani Nikula Cc: Daniel Vetter Cc: Yetunde Adebisi Signed-off-by: Deepak M --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_dsi.c | 17 +++- drivers/gpu/drm/i915/intel_dsi.h | 4 + drivers/gpu/drm/i915/intel_dsi_cabc.c | 179 ++ drivers/gpu/drm/i915/intel_panel.c| 4 + 6 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/i915/intel_dsi_cabc.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 0851de07..2c69ed4 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -82,6 +82,7 @@ i915-y += dvo_ch7017.o \ intel_dp.o \ intel_dsi.o \ intel_dsi_panel_vbt.o \ + intel_dsi_cabc.o \ intel_dsi_pll.o \ intel_dvo.o \ intel_hdmi.o \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6644c2e..43dd10e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3488,7 +3488,7 @@ void intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value, enum intel_sbi_destination destination); u32 vlv_flisdsi_read(struct drm_i915_private *dev_priv, u32 reg); void vlv_flisdsi_write(struct drm_i915_private *dev_priv, u32 reg, u32 val); - +int intel_dsi_cabc_init_backlight_funcs(struct intel_connector *intel_connector); int intel_gpu_freq(struct drm_i915_private *dev_priv, int val); int intel_freq_opcode(struct drm_i915_private *dev_priv, int val); diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index b928c50..caa65df 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -1171,8 +1171,23 @@ void intel_dsi_init(struct drm_device *dev) intel_dsi->ports = (1 << PORT_C); } - if (dev_priv->vbt.dsi.config->dual_link) + if (dev_priv->vbt.dsi.config->dual_link) { intel_dsi->ports = ((1 << PORT_A) | (1 << PORT_C)); + switch (dev_priv->vbt.dsi.config->dl_cabc_port) { + case CABC_PORT_A: + intel_dsi->bkl_dcs_ports = (1 << PORT_A); + break; + case CABC_PORT_C: + intel_dsi->bkl_dcs_ports = (1 << PORT_C); + break; + case CABC_PORT_A_AND_C: + intel_dsi->bkl_dcs_ports = intel_dsi->ports; + break; + default: + DRM_ERROR("Unknown MIPI ports for sending DCS\n"); + } + } else + intel_dsi->bkl_dcs_ports = intel_dsi->ports; /* Create a DSI host (and a device) for each port. */ for_each_dsi_port(port, intel_dsi->ports) { diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 6dfa0e3..466da2d 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -34,6 +34,10 @@ #define DSI_DUAL_LINK_FRONT_BACK 1 #define DSI_DUAL_LINK_PIXEL_ALT2 +#define CABC_PORT_A 0x00 +#define CABC_PORT_C 0x01 +#define CABC_PORT_A_AND_C 0x02 + struct intel_dsi_host; struct intel_dsi { diff --git a/drivers/gpu/drm/i915/intel_dsi_cabc.c b/drivers/gpu/drm/i915/intel_dsi_cabc.c new file mode 100644 index 000..d14a669 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dsi_cabc.c @@ -0,0 +1,179 @@ +/* + * Copyright © 2006-2010 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNE
[CABC PATCH 0/2] CABC patch list
CABC stands for the Content Adaptive Backlight Control. In the normal display the backlight which we see is due to the backlight which is being modulated by the filter, which is inturn dependent on the image. In brief the CABC does the histogram analysis of the image and then controls the filter and backlight. For example in CABC to display the dark image the backlight is dimmed and then controlls the filter to allow more light, because of which is power consuption will be reduced. Below are the initial set of patches which supports the CABC. A field exits in the mipi configuration of the VBT which when enabled indiactes the CABC is supported. Depending on this filed the backlight control function pointer are initialized in the intel_panel.c file. In case of dual link panels depending on the panel the DCS commands have to be send to either PORT A, PORT C or both PORT A and PORT C. Again a filed is added in the VBT to get this data from the version 197 onwards. One of the below patches parses these fields from the VBT. Addressed the review comments of Jani, which were mentioned in the below https://lists.freedesktop.org/archives/intel-gfx/2015-November/081233.html Cc: Jani Nikula Cc: Daniel Vetter Cc: Yetunde Adebisi Deepak M (2): drm/i915: Parsing the PWM cntrl and CABC ON/OFF fileds in VBT drm/i915: CABC support for backlight control drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/intel_bios.c | 10 ++ drivers/gpu/drm/i915/intel_bios.h | 5 +- drivers/gpu/drm/i915/intel_dsi.c | 17 +++- drivers/gpu/drm/i915/intel_dsi.h | 13 +++ drivers/gpu/drm/i915/intel_dsi_cabc.c | 179 ++ drivers/gpu/drm/i915/intel_panel.c| 4 + 8 files changed, 228 insertions(+), 3 deletions(-) create mode 100644 drivers/gpu/drm/i915/intel_dsi_cabc.c -- 1.9.1
[CABC PATCH 1/2] drm/i915: Parsing the PWM cntrl and CABC ON/OFF fileds in VBT
For dual link panel scenarios there are new fileds added in the VBT which indicate on which port the PWM cntrl and CABC ON/OFF commands needs to be sent. v2: Moving the comment to intel_dsi.h(Jani) Cc: Jani Nikula Cc: Daniel Vetter Cc: Yetunde Adebisi Signed-off-by: Deepak M --- drivers/gpu/drm/i915/intel_bios.c | 10 ++ drivers/gpu/drm/i915/intel_bios.h | 5 - drivers/gpu/drm/i915/intel_dsi.h | 9 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index bf62a19..4f5c0df 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -747,6 +747,16 @@ parse_mipi_config(struct drm_i915_private *dev_priv, return; } + /* +* These fileds are introduced from the VBT version 197 onwards, +* so making sure that these bits are set zero in the pervious +* versions. +*/ + if (dev_priv->vbt.dsi.config->dual_link && bdb->version < 197) { + dev_priv->vbt.dsi.config->dl_cabc_port = 0; + dev_priv->vbt.dsi.config->pwm_bkl_ctrl = 0; + } + /* We have mandatory mipi config blocks. Initialize as generic panel */ dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID; } diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 350d4e0..8f295fd 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -846,7 +846,10 @@ struct mipi_config { u16 dual_link:2; u16 lane_cnt:2; u16 pixel_overlap:3; - u16 rsvd3:9; + u16 rgb_flip:1; + u16 dl_cabc_port:2; + u16 pwm_bkl_ctrl:2; + u16 rsvd3:4; u16 rsvd4; diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index de7be7f..6dfa0e3 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h @@ -74,6 +74,15 @@ struct intel_dsi { u8 escape_clk_div; u8 dual_link; + + /* +* Below field will inform us on which port the panel blk_cntrl +* and CABC ON/OFF commands needs to be sent in case of dual link +* panels +*/ + u8 bkl_dcs_ports; + u8 pwm_blk_ctrl; + u8 pixel_overlap; u32 port_bits; u32 bw_timer; -- 1.9.1
[PATCH v6 03/11] drm/hisilicon: Add crtc driver for ADE
Hi, On 1 March 2016 at 02:48, Archit Taneja wrote: > > > On 2/26/2016 2:10 PM, Xinliang Liu wrote: >> >> Add crtc funcs and helper funcs for ADE. >> >> v6: >> - Cleanup reg-names dt parsing. >> v5: >> - Use syscon to access ADE media NOC QoS registers instread of directly >>writing registers. >> - Use reset controller to reset ADE instead of directly writing registers. >> v4: None. >> v3: >> - Make ade as the master driver. >> - Use port to connect with encoder. >> - A few cleanup. >> v2: >> - Remove abtraction layer. >> >> Signed-off-by: Xinliang Liu >> --- >> drivers/gpu/drm/hisilicon/kirin/Makefile| 3 +- >> drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h | 290 +++ >> drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 452 >> >> drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 15 + >> drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.h | 8 + >> 5 files changed, 767 insertions(+), 1 deletion(-) >> create mode 100644 drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h >> create mode 100644 drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> >> diff --git a/drivers/gpu/drm/hisilicon/kirin/Makefile >> b/drivers/gpu/drm/hisilicon/kirin/Makefile >> index cb346de47d48..2a61ab006ddb 100644 >> --- a/drivers/gpu/drm/hisilicon/kirin/Makefile >> +++ b/drivers/gpu/drm/hisilicon/kirin/Makefile >> @@ -1,3 +1,4 @@ >> -kirin-drm-y := kirin_drm_drv.o >> +kirin-drm-y := kirin_drm_drv.o \ >> + kirin_drm_ade.o >> >> obj-$(CONFIG_DRM_HISI_KIRIN) += kirin-drm.o >> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h >> b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h >> new file mode 100644 >> index ..eb444b899c7b >> --- /dev/null >> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_ade_reg.h >> @@ -0,0 +1,290 @@ >> +/* >> + * Copyright (c) 2016 Linaro Limited. >> + * Copyright (c) 2014-2016 Hisilicon Limited. >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + * >> + */ >> + >> +#ifndef __KIRIN_ADE_REG_H__ >> +#define __KIRIN_ADE_REG_H__ >> + >> +/* >> + * ADE Registers >> + */ >> +#define MASK(x)(BIT(x) - 1) >> + >> +#define ADE_CTRL 0x0004 >> +#define FRM_END_START_OFST 0 >> +#define FRM_END_START_MASK MASK(2) >> +#define ADE_CTRL1 0x008C >> +#define AUTO_CLK_GATE_EN_OFST 0 >> +#define AUTO_CLK_GATE_EN BIT(0) >> +#define ADE_ROT_SRC_CFG0x0010 >> +#define ADE_DISP_SRC_CFG 0x0018 >> +#define ADE_WDMA2_SRC_CFG 0x001C >> +#define ADE_SEC_OVLY_SRC_CFG 0x0020 >> +#define ADE_WDMA3_SRC_CFG 0x0024 >> +#define ADE_OVLY1_TRANS_CFG0x002C >> +#define ADE_EN 0x0100 >> +#define ADE_DISABLE0 >> +#define ADE_ENABLE 1 >> +#define INTR_MASK_CPU(x) (0x0C10 + (x) * 0x4) >> +#define ADE_FRM_DISGARD_CTRL 0x00A4 >> +/* reset and reload regs */ >> +#define ADE_SOFT_RST_SEL(x)(0x0078 + (x) * 0x4) >> +#define ADE_RELOAD_DIS(x) (0x00AC + (x) * 0x4) >> +#define RDMA_OFST 0 >> +#define CLIP_OFST 15 >> +#define SCL_OFST 21 >> +#define CTRAN_OFST 24 >> +#define OVLY_OFST 37 /* 32+5 */ >> +/* channel regs */ >> +#define RD_CH_PE(x)(0x1000 + (x) * 0x80) >> +#define RD_CH_CTRL(x) (0x1004 + (x) * 0x80) >> +#define RD_CH_ADDR(x) (0x1008 + (x) * 0x80) >> +#define RD_CH_SIZE(x) (0x100C + (x) * 0x80) >> +#define RD_CH_STRIDE(x)(0x1010 + (x) * 0x80) >> +#define RD_CH_SPACE(x) (0x1014 + (x) * 0x80) >> +#define RD_CH_PARTIAL_SIZE(x) (0x1018 + (x) * 0x80) >> +#define RD_CH_PARTIAL_SPACE(x) (0x101C + (x) * 0x80) >> +#define RD_CH_EN(x)(0x1020 + (x) * 0x80) >> +#define RD_CH_STATUS(x)(0x1024 + (x) * 0x80) >> +#define RD_CH_DISP_CTRL0x1404 >> +#define RD_CH_DISP_ADDR0x1408 >> +#define RD_CH_DISP_SIZE0x140C >> +#define RD_CH_DISP_STRIDE 0x1410 >> +#define RD_CH_DISP_SPACE 0x1414 >> +#define RD_CH_DISP_EN 0x142C >> +/* clip regs */ >> +#define ADE_CLIP_DISABLE(x)(0x6800 + (x) * 0x100) >> +#define ADE_CLIP_SIZE0(x) (0x6804 + (x) * 0x100) >> +#define ADE_CLIP_SIZE1(x) (0x6808 + (x) * 0x100) >> +#define ADE_CLIP_SIZE2(x) (0x680C + (x) * 0x100) >> +#define ADE_CLIP_CFG_OK(x) (0x6810 + (x) * 0x100) >> +/* scale regs */ >> +#define ADE_SCL1_MUX_CFG 0x000
[PATCH v6 04/11] drm/hisilicon: Add plane driver for ADE
Hi, On 1 March 2016 at 02:48, Archit Taneja wrote: > > > On 2/26/2016 2:10 PM, Xinliang Liu wrote: >> >> Add plane funcs and helper funcs for ADE. >> >> v6: None. >> v5: None. >> v4: None. >> v3: >> - A few cleanup. >> v2: >> - Remove abtraction layer. >> >> Signed-off-by: Xinliang Liu >> --- >> drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 535 >> +++- >> 1 file changed, 534 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> index bb93616dcf3d..aa2cf75cab39 100644 >> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> @@ -27,13 +27,23 @@ >> #include >> #include >> #include >> +#include >> +#include >> +#include >> >> #include "kirin_drm_drv.h" >> #include "kirin_ade_reg.h" >> >> +#define PRIMARY_CH ADE_CH1 /* primary plane */ >> +#define OUT_OVLY ADE_OVLY2 /* output overlay compositor */ > > > Could you briefly explain this overlay/channel mapping? It looks like > it's something that is hard coded at the moment. > > Do channels map to planes, and OVLs map to crtcs? > Yes, channels map to planes. But not sure if OVLs is map to crtcs. IMO, crtc mean an individual display pipe line. Here, OVLs are the overlay compositor. There three OVLs in this chip, we choose OVLY2 for online display now. Also see the Hardware Detail part of cover patch. > >> +#define ADE_DEBUG 1 >> + >> #define to_ade_crtc(crtc) \ >> container_of(crtc, struct ade_crtc, base) >> >> +#define to_ade_plane(plane) \ >> + container_of(plane, struct ade_plane, base) >> + >> struct ade_hw_ctx { >> void __iomem *base; >> struct regmap *noc_regmap; >> @@ -52,11 +62,76 @@ struct ade_crtc { >> u32 out_format; >> }; >> >> +struct ade_plane { >> + struct drm_plane base; >> + void *ctx; >> + u8 ch; /* channel */ >> +}; >> + >> struct ade_data { >> struct ade_crtc acrtc; >> + struct ade_plane aplane[ADE_CH_NUM]; >> struct ade_hw_ctx ctx; >> }; >> >> +/* ade-format info: */ >> +struct ade_format { >> + u32 pixel_format; >> + enum ade_fb_format ade_format; >> +}; >> + >> +static const struct ade_format ade_formats[] = { >> + /* 16bpp RGB: */ >> + { DRM_FORMAT_RGB565, ADE_RGB_565 }, >> + { DRM_FORMAT_BGR565, ADE_BGR_565 }, >> + /* 24bpp RGB: */ >> + { DRM_FORMAT_RGB888, ADE_RGB_888 }, >> + { DRM_FORMAT_BGR888, ADE_BGR_888 }, >> + /* 32bpp [A]RGB: */ >> + { DRM_FORMAT_XRGB, ADE_XRGB_ }, >> + { DRM_FORMAT_XBGR, ADE_XBGR_ }, >> + { DRM_FORMAT_RGBA, ADE_RGBA_ }, >> + { DRM_FORMAT_BGRA, ADE_BGRA_ }, >> + { DRM_FORMAT_ARGB, ADE_ARGB_ }, >> + { DRM_FORMAT_ABGR, ADE_ABGR_ }, >> +}; >> + >> +static const u32 channel_formats1[] = { >> + /* channel 1,2,3,4 */ >> + DRM_FORMAT_RGB565, DRM_FORMAT_BGR565, DRM_FORMAT_RGB888, >> + DRM_FORMAT_BGR888, DRM_FORMAT_XRGB, DRM_FORMAT_XBGR, >> + DRM_FORMAT_RGBA, DRM_FORMAT_BGRA, DRM_FORMAT_ARGB, >> + DRM_FORMAT_ABGR >> +}; >> + >> +u32 ade_get_channel_formats(u8 ch, const u32 **formats) >> +{ >> + switch (ch) { >> + case ADE_CH1: >> + *formats = channel_formats1; >> + return ARRAY_SIZE(channel_formats1); >> + default: >> + DRM_ERROR("no this channel %d\n", ch); >> + *formats = NULL; >> + return 0; >> + } >> +} >> + >> +/* convert from fourcc format to ade format */ >> +static u32 ade_get_format(u32 pixel_format) >> +{ >> + int i; >> + >> + for (i = 0; i < ARRAY_SIZE(ade_formats); i++) >> + if (ade_formats[i].pixel_format == pixel_format) >> + return ade_formats[i].ade_format; >> + >> + /* not found */ >> + DRM_ERROR("Not found pixel format!!fourcc_format= %d\n", >> + pixel_format); >> + return ADE_FORMAT_NOT_SUPPORT; >> +} >> + >> static void ade_update_reload_bit(void __iomem *base, u32 bit_num, u32 >> val) >> { >> u32 bit_ofst, reg_num; >> @@ -89,7 +164,7 @@ static void ade_init(struct ade_hw_ctx *ctx) >> /* clear overlay */ >> writel(0, base + ADE_OVLY1_TRANS_CFG); >> writel(0, base + ADE_OVLY_CTL); >> - writel(0, base + ADE_OVLYX_CTL(ADE_OVLY2)); >> + writel(0, base + ADE_OVLYX_CTL(OUT_OVLY)); >> /* clear reset and reload regs */ >> writel(MASK(32), base + ADE_SOFT_RST_SEL(0)); >> writel(MASK(32), base + ADE_SOFT_RST_SEL(1)); >> @@ -147,6 +222,10 @@ static void ade_ldi_set_mode(struct ade_crtc *acrtc, >> mode->clock * 1000, ret); >> adj_mode->clock = clk_get_rate(ctx->ade_pix_clk) / 1000; >> >> + /* set overlay compositor output size */ >> +
[PATCH v6 05/11] drm/hisilicon: Add vblank driver for ADE
Hi, On 1 March 2016 at 02:48, Archit Taneja wrote: > > > On 2/26/2016 2:10 PM, Xinliang Liu wrote: >> >> Add vblank irq handle. >> >> v6: None. >> v5: None. >> v4: None. >> v3: >> - Remove hisi_get_crtc_from_index func. >> - A few cleanup. >> v2: >> - Remove abtraction layer. >> >> Signed-off-by: Xinliang Liu >> --- >> drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 62 >> + >> drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 14 +- >> 2 files changed, 75 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> index aa2cf75cab39..749382952ab7 100644 >> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >> @@ -292,6 +292,59 @@ static void ade_set_medianoc_qos(struct ade_crtc >> *acrtc) >>SOCKET_QOS_EN, SOCKET_QOS_EN); >> } >> >> +static int ade_enable_vblank(struct drm_device *dev, unsigned int pipe) >> +{ >> + struct kirin_drm_private *priv = dev->dev_private; >> + struct ade_crtc *acrtc = to_ade_crtc(priv->crtc[pipe]); >> + struct ade_hw_ctx *ctx = acrtc->ctx; >> + void __iomem *base = ctx->base; >> + >> + if (!ctx->power_on) >> + (void)ade_power_up(ctx); >> + >> + ade_update_bits(base + LDI_INT_EN, FRAME_END_INT_EN_OFST, >> + MASK(1), 1); >> + >> + return 0; >> +} >> + >> +static void ade_disable_vblank(struct drm_device *dev, unsigned int pipe) >> +{ >> + struct kirin_drm_private *priv = dev->dev_private; >> + struct ade_crtc *acrtc = to_ade_crtc(priv->crtc[pipe]); >> + struct ade_hw_ctx *ctx = acrtc->ctx; >> + void __iomem *base = ctx->base; >> + >> + if (!ctx->power_on) { >> + DRM_ERROR("power is down! vblank disable fail\n"); >> + return; >> + } >> + >> + ade_update_bits(base + LDI_INT_EN, FRAME_END_INT_EN_OFST, >> + MASK(1), 0); >> +} >> + >> +static irqreturn_t ade_irq_handler(int irq, void *data) >> +{ >> + struct ade_crtc *acrtc = data; >> + struct ade_hw_ctx *ctx = acrtc->ctx; >> + struct drm_crtc *crtc = &acrtc->base; >> + void __iomem *base = ctx->base; >> + u32 status; >> + >> + status = readl(base + LDI_MSK_INT); >> + DRM_DEBUG_VBL("LDI IRQ: status=0x%X\n", status); >> + >> + /* vblank irq */ >> + if (status & BIT(FRAME_END_INT_EN_OFST)) { >> + ade_update_bits(base + LDI_INT_CLR, FRAME_END_INT_EN_OFST, >> + MASK(1), 1); >> + drm_crtc_handle_vblank(crtc); >> + } >> + >> + return IRQ_HANDLED; >> +} >> + >> static void ade_display_enable(struct ade_crtc *acrtc) >> { >> struct ade_hw_ctx *ctx = acrtc->ctx; >> @@ -967,6 +1020,15 @@ int ade_drm_init(struct drm_device *dev) >> if (ret) >> return ret; >> >> + /* vblank irq init */ >> + ret = devm_request_irq(dev->dev, ctx->irq, ade_irq_handler, >> + DRIVER_IRQ_SHARED, dev->driver->name, >> acrtc); > > > This isn't the way we set up interrupts for kms drivers. We need to > provide the handler in drm_driver and call drm_irq_install. I prefer to set up interrupts here for two reasons. One is that it is easy to pass any interrupt private "void * data" to the interrupt handler here. As I discussed with Daniel Vetter before: https://lkml.org/lkml/2015/9/10/204. Second is setting up interrupt here in the specific SoC display controller driver, make other SoC reuse the kirin_drm_drv.c code easily. Different Hisilicon SoC may has different display controller interrupts. > > >> + if (ret) >> + return ret; >> + dev->driver->get_vblank_counter = drm_vblank_no_hw_counter; >> + dev->driver->enable_vblank = ade_enable_vblank; >> + dev->driver->disable_vblank = ade_disable_vblank; >> + >> return 0; >> } >> >> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c >> b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c >> index 055729c1889c..723888feb760 100644 >> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c >> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c >> @@ -32,6 +32,7 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev) >> { >> struct kirin_drm_private *priv = dev->dev_private; >> >> + drm_vblank_cleanup(dev); >> dc_ops->cleanup(dev); >> drm_mode_config_cleanup(dev); >> devm_kfree(dev->dev, priv); >> @@ -85,11 +86,22 @@ static int kirin_drm_kms_init(struct drm_device *dev) >> goto err_dc_cleanup; >> } >> >> + /* vblank init */ >> + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); >> + if (ret) { >> + DRM_ERROR("failed to initialize vblank.\n"); >> + goto err_unbind_all; >> + } >>
[PATCH v6 07/11] drm/hisilicon: Add designware dsi encoder driver
Hi, On 1 March 2016 at 02:49, Archit Taneja wrote: > > > On 2/26/2016 2:10 PM, Xinliang Liu wrote: >> >> Add DesignWare MIPI DSI Host Controller v1.02 encoder driver >> for hi6220 SoC. >> >> v6: >> - Change "pclk_dsi" to "pclk". >> v5: None. >> v4: None. >> v3: >> - Rename file name to dw_drm_dsi.c >> - Make encoder type as DRM_MODE_ENCODER_DSI. >> - A few cleanup. >> v2: >> - Remove abtraction layer. >> >> Signed-off-by: Xinliang Liu >> Signed-off-by: Xinwei Kong >> Signed-off-by: Andy Green >> --- >> drivers/gpu/drm/hisilicon/kirin/Kconfig | 1 + >> drivers/gpu/drm/hisilicon/kirin/Makefile | 3 +- >> drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 743 >> +++ >> drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h | 83 +++ >> 4 files changed, 829 insertions(+), 1 deletion(-) >> create mode 100644 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> create mode 100644 drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h >> >> diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig >> b/drivers/gpu/drm/hisilicon/kirin/Kconfig >> index 3ac4b8edeac1..de0d454c5c13 100644 >> --- a/drivers/gpu/drm/hisilicon/kirin/Kconfig >> +++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig >> @@ -4,6 +4,7 @@ config DRM_HISI_KIRIN >> select DRM_KMS_HELPER >> select DRM_GEM_CMA_HELPER >> select DRM_KMS_CMA_HELPER >> + select DRM_MIPI_DSI >> help >> Choose this option if you have a hisilicon Kirin >> chipsets(hi6220). >> If M is selected the module will be called kirin-drm. >> diff --git a/drivers/gpu/drm/hisilicon/kirin/Makefile >> b/drivers/gpu/drm/hisilicon/kirin/Makefile >> index 2a61ab006ddb..5dcd0d4328b6 100644 >> --- a/drivers/gpu/drm/hisilicon/kirin/Makefile >> +++ b/drivers/gpu/drm/hisilicon/kirin/Makefile >> @@ -1,4 +1,5 @@ >> kirin-drm-y := kirin_drm_drv.o \ >> - kirin_drm_ade.o >> + kirin_drm_ade.o \ >> + dw_drm_dsi.o >> >> obj-$(CONFIG_DRM_HISI_KIRIN) += kirin-drm.o >> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> new file mode 100644 >> index ..8329148cc89d >> --- /dev/null >> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> @@ -0,0 +1,743 @@ >> +/* >> + * DesignWare MIPI DSI Host Controller v1.02 driver >> + * >> + * Copyright (c) 2016 Linaro Limited. >> + * Copyright (c) 2014-2016 Hisilicon Limited. >> + * >> + * Author: >> + * Xinliang Liu >> + * Xinliang Liu >> + * Xinwei Kong >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License version 2 as >> + * published by the Free Software Foundation. >> + * >> + */ >> + >> +#include >> +#include >> +#include >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#include "dw_dsi_reg.h" >> + >> +#define MAX_TX_ESC_CLK(10) >> +#define ROUND(x, y) ((x) / (y) + ((x) % (y) * 10 / (y) >= 5 ? 1 : 0)) >> +#define PHY_REF_CLK_RATE 1920 >> +#define PHY_REF_CLK_PERIOD_PS (10 / (PHY_REF_CLK_RATE / 1000)) >> + >> +#define encoder_to_dsi(encoder) \ >> + container_of(encoder, struct dw_dsi, encoder) >> +#define host_to_dsi(host) \ >> + container_of(host, struct dw_dsi, host) >> + >> +struct mipi_phy_params { >> + u32 clk_t_lpx; >> + u32 clk_t_hs_prepare; >> + u32 clk_t_hs_zero; >> + u32 clk_t_hs_trial; >> + u32 clk_t_wakeup; >> + u32 data_t_lpx; >> + u32 data_t_hs_prepare; >> + u32 data_t_hs_zero; >> + u32 data_t_hs_trial; >> + u32 data_t_ta_go; >> + u32 data_t_ta_get; >> + u32 data_t_wakeup; >> + u32 hstx_ckg_sel; >> + u32 pll_fbd_div5f; >> + u32 pll_fbd_div1f; >> + u32 pll_fbd_2p; >> + u32 pll_enbwt; >> + u32 pll_fbd_p; >> + u32 pll_fbd_s; >> + u32 pll_pre_div1p; >> + u32 pll_pre_p; >> + u32 pll_vco_750M; >> + u32 pll_lpf_rs; >> + u32 pll_lpf_cs; >> + u32 clklp2hs_time; >> + u32 clkhs2lp_time; >> + u32 lp2hs_time; >> + u32 hs2lp_time; >> + u32 clk_to_data_delay; >> + u32 data_to_clk_delay; >> + u32 lane_byte_clk_kHz; >> + u32 clk_division; >> +}; >> + >> +struct dsi_hw_ctx { >> + void __iomem *base; >> + struct clk *pclk; >> +}; >> + >> +struct dw_dsi { >> + struct drm_encoder encoder; >> + struct drm_display_mode cur_mode; >> + struct dsi_hw_ctx *ctx; >> + struct mipi_phy_params phy; >> + >> + u32 lanes; >> + enum mipi_dsi_pixel_format format; >> + unsigned long mode_flags; >> + bool enable; >> +}; >> + >> +struct dsi_data { >> + struct dw_dsi dsi; >> + struct dsi_hw_ctx ctx; >> +}; >> + >> +struct dsi_phy_range { >> + u32 min_range_kHz; >> + u32 max_range_kHz; >> + u32 pll_vco_750M; >> + u32 hstx_ckg_sel; >> +}; >> + >> +stat
[PATCH v6 08/11] drm/hisilicon: Add designware dsi host driver
Hi, On 1 March 2016 at 02:51, Archit Taneja wrote: > > > On 2/26/2016 2:10 PM, Xinliang Liu wrote: >> >> Add DesignWare dsi host driver for hi6220 SoC. >> >> v6: None. >> v5: None. >> v4: None. >> v3: None. >> v2: >> - Remove abtraction layer. > > > Reviewed-by: Archit Taneja Thanks :-) Best, -xinliang > > >> >> Signed-off-by: Xinliang Liu >> --- >> drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 50 >> >> 1 file changed, 50 insertions(+) >> >> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> index 8329148cc89d..f15798b61451 100644 >> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> @@ -79,6 +79,7 @@ struct dsi_hw_ctx { >> >> struct dw_dsi { >> struct drm_encoder encoder; >> + struct mipi_dsi_host host; >> struct drm_display_mode cur_mode; >> struct dsi_hw_ctx *ctx; >> struct mipi_phy_params phy; >> @@ -642,6 +643,51 @@ static int dw_drm_encoder_init(struct device *dev, >> return 0; >> } >> >> +static int dsi_host_attach(struct mipi_dsi_host *host, >> + struct mipi_dsi_device *mdsi) >> +{ >> + struct dw_dsi *dsi = host_to_dsi(host); >> + >> + if (mdsi->lanes < 1 || mdsi->lanes > 4) { >> + DRM_ERROR("dsi device params invalid\n"); >> + return -EINVAL; >> + } >> + >> + dsi->lanes = mdsi->lanes; >> + dsi->format = mdsi->format; >> + dsi->mode_flags = mdsi->mode_flags; >> + >> + return 0; >> +} >> + >> +static int dsi_host_detach(struct mipi_dsi_host *host, >> + struct mipi_dsi_device *mdsi) >> +{ >> + /* do nothing */ >> + return 0; >> +} >> + >> +static const struct mipi_dsi_host_ops dsi_host_ops = { >> + .attach = dsi_host_attach, >> + .detach = dsi_host_detach, >> +}; >> + >> +static int dsi_host_init(struct device *dev, struct dw_dsi *dsi) >> +{ >> + struct mipi_dsi_host *host = &dsi->host; >> + int ret; >> + >> + host->dev = dev; >> + host->ops = &dsi_host_ops; >> + ret = mipi_dsi_host_register(host); >> + if (ret) { >> + DRM_ERROR("failed to register dsi host\n"); >> + return ret; >> + } >> + >> + return 0; >> +} >> + >> static int dsi_bind(struct device *dev, struct device *master, void >> *data) >> { >> struct dsi_data *ddata = dev_get_drvdata(dev); >> @@ -653,6 +699,10 @@ static int dsi_bind(struct device *dev, struct device >> *master, void *data) >> if (ret) >> return ret; >> >> + ret = dsi_host_init(dev, dsi); >> + if (ret) >> + return ret; >> + >> return 0; >> } >> >> > > -- > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, > a Linux Foundation Collaborative Project
[PATCH v6 09/11] drm/hisilicon: Add support for external bridge
On 1 March 2016 at 02:53, Archit Taneja wrote: > > > On 2/26/2016 2:10 PM, Xinliang Liu wrote: >> >> Add support for external HDMI bridge. >> >> v6: None. >> v5: None. >> v4: None. >> v3: >> - Fix a typo: s/exteranl/external. >> v2: >> - Remove abtraction layer. >> > > Reviewed-by: Archit Taneja Thanks :-) Best, -xinliang > > >> Signed-off-by: Xinliang Liu >> --- >> drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 52 >> >> 1 file changed, 52 insertions(+) >> >> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> index f15798b61451..c2c406446513 100644 >> --- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >> @@ -79,6 +79,7 @@ struct dsi_hw_ctx { >> >> struct dw_dsi { >> struct drm_encoder encoder; >> + struct drm_bridge *bridge; >> struct mipi_dsi_host host; >> struct drm_display_mode cur_mode; >> struct dsi_hw_ctx *ctx; >> @@ -688,6 +689,25 @@ static int dsi_host_init(struct device *dev, struct >> dw_dsi *dsi) >> return 0; >> } >> >> +static int dsi_bridge_init(struct drm_device *dev, struct dw_dsi *dsi) >> +{ >> + struct drm_encoder *encoder = &dsi->encoder; >> + struct drm_bridge *bridge = dsi->bridge; >> + int ret; >> + >> + /* associate the bridge to dsi encoder */ >> + encoder->bridge = bridge; >> + bridge->encoder = encoder; >> + >> + ret = drm_bridge_attach(dev, bridge); >> + if (ret) { >> + DRM_ERROR("failed to attach external bridge\n"); >> + return ret; >> + } >> + >> + return 0; >> +} >> + >> static int dsi_bind(struct device *dev, struct device *master, void >> *data) >> { >> struct dsi_data *ddata = dev_get_drvdata(dev); >> @@ -703,6 +723,10 @@ static int dsi_bind(struct device *dev, struct device >> *master, void *data) >> if (ret) >> return ret; >> >> + ret = dsi_bridge_init(drm_dev, dsi); >> + if (ret) >> + return ret; >> + >> return 0; >> } >> >> @@ -719,8 +743,36 @@ static const struct component_ops dsi_ops = { >> static int dsi_parse_dt(struct platform_device *pdev, struct dw_dsi >> *dsi) >> { >> struct dsi_hw_ctx *ctx = dsi->ctx; >> + struct device_node *np = pdev->dev.of_node; >> + struct device_node *endpoint, *bridge_node; >> + struct drm_bridge *bridge; >> struct resource *res; >> >> + /* >> +* Get the endpoint node. In our case, dsi has one output port1 >> +* to which the external HDMI bridge is connected. >> +*/ >> + endpoint = of_graph_get_endpoint_by_regs(np, 1, -1); >> + if (!endpoint) { >> + DRM_ERROR("no valid endpoint node\n"); >> + return -ENODEV; >> + } >> + of_node_put(endpoint); >> + >> + bridge_node = of_graph_get_remote_port_parent(endpoint); >> + if (!bridge_node) { >> + DRM_ERROR("no valid bridge node\n"); >> + return -ENODEV; >> + } >> + of_node_put(bridge_node); >> + >> + bridge = of_drm_find_bridge(bridge_node); >> + if (!bridge) { >> + DRM_INFO("wait for external HDMI bridge driver.\n"); >> + return -EPROBE_DEFER; >> + } >> + dsi->bridge = bridge; >> + >> ctx->pclk = devm_clk_get(&pdev->dev, "pclk"); >> if (IS_ERR(ctx->pclk)) { >> DRM_ERROR("failed to get pclk clock\n"); >> > > -- > Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, > a Linux Foundation Collaborative Project
[PATCH 0/8] drm: atmel-hlcdc: various fixes/improvements
On Wed, 6 Jan 2016 11:19:21 +0100 Boris Brezillon wrote: > Hello, > > This series is a collection of fixes and improvements for the > atmel-hlcdc driver. > > The main feature added here is the support for external RGB -> XXX > bridges (patch 6 and 7). > > The first patch is a fix preventing a potential memory leak. > Patch 2 is adding support for asynchronous mode setting, which was > supported before the migration to atomic mode setting. > > Patch 3 is just a minor fix to expose the real encoder and connector > types (we are currently exposing an LVDS encoder/connector, which is > wrong since the display controller output the pixel stream in raw > RGB). > > Patch 4 is removing useless fields and functions which were left > when moving to atomic modesetting. > > And patch 8 is just a cosmetic patch moving the mode checking code > from ->atomic_check() to ->mode_fixup(). Dave, Daniel, any comment on this series (AKA ping)? > > Best Regards, > > Boris > > Boris Brezillon (8): > drm: atmel-hlcdc: add a ->cleanup_fb() operation > drm: atmel-hlcdc: support asynchronous atomic commit operations > drm: atmel-hlcdc: fix connector and encoder types > drm: atmel-hlcdc: remove leftovers from atomic mode setting migration > drm: atmel-hlcdc: support extended timing ranges on sama5d4 and > sama5d2 > drm: atmel-hlcdc: move output mode selection in CRTC implementation > drm: atmel-hlcdc: rework the output code to support drm bridges > drm: atmel-hlcdc: check display mode validity in crtc->mode_fixup() > > drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 148 +- > drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 123 ++- > drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h | 16 ++ > drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c | 249 > ++- > drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 22 +- > 5 files changed, 400 insertions(+), 158 deletions(-) > -- Boris Brezillon, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com
enable display using drm
Hi. I want to know if it's possible (enable/disable) the display using some function of drm. I have looking for but I don't find nothing about this. Regards! -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160301/da4a48d7/attachment.html>
[PATCH v4 1/5] staging/android: add num_fences field to struct sync_file_info
2016-03-01 Dan Carpenter : > This breaks userspace. You used to be able to figure it out from > info->len - sizeof(struct sync_file_info). It does. We are breaking this on purpose to clean up the API for de-staging. Gustavo
[PATCH] staging/android: refactor SYNC_IOC_FILE_INFO
Hi Maarten, 2016-03-01 Maarten Lankhorst : > Op 29-02-16 om 23:08 schreef Gustavo Padovan: > > Hi Maarten, > > > > 2016-02-29 Maarten Lankhorst : > > > >> Op 26-02-16 om 22:00 schreef Gustavo Padovan: > >>> From: Gustavo Padovan > >>> > >>> Change SYNC_IOC_FILE_INFO behaviour to avoid future API breaks and > >>> optimize buffer allocation. In the new approach the ioctl needs to be > >>> called > >>> twice to retrieve the array of fence_infos pointed by > >>> info->sync_fence_info. > >>> > >>> The first call should pass num_fences = 0, the kernel will then fill > >>> info->num_fences. Userspace receives back the number of fences and > >>> allocates a buffer size num_fences * sizeof(struct sync_fence_info) on > >>> info->sync_fence_info. > >>> > >>> It then call the ioctl again passing num_fences received in > >>> info->num_fences. > >>> The kernel checks if info->num_fences > 0 and if yes it fill > >>> info->sync_fence_info with an array containing all fence_infos. > >>> > >>> info->len now represents the length of the buffer sync_fence_info points > >>> to. Also, info->sync_fence_info was converted to __u64 pointer. > >>> > >>> An example userspace code would be: > >>> > >>> struct sync_file_info *info; > >>> int err, size, num_fences; > >>> > >>> info = malloc(sizeof(*info)); > >>> > >>> memset(info, 0, sizeof(*info)); > >>> > >>> err = ioctl(fd, SYNC_IOC_FILE_INFO, info); > >>> num_fences = info->num_fences; > >>> > >>> if (num_fences) { > >>> memset(info, 0, sizeof(*info)); > >> Would this memset still be needed if we didn't check for nulls in > >> info->status and info->name ? > >> > >> Seems to me that it could be skipped in that case. > > Yes, I agree. > > > >>> size = sizeof(struct sync_fence_info) * num_fences; > >>> info->len = size; > >>> info->num_fences = num_fences; > >>> info->sync_fence_info = (uint64_t) calloc(num_fences, > >>> sizeof(struct > >>> sync_fence_info)); > >>> > >>> err = ioctl(fd, SYNC_IOC_FILE_INFO, info); > >>> } > >>> > >>> v2: fix fence_info memory leak > >>> > >>> Signed-off-by: Gustavo Padovan > >>> --- > >>> drivers/staging/android/sync.c | 52 > >>> + > >>> drivers/staging/android/uapi/sync.h | 9 +++ > >>> 2 files changed, 45 insertions(+), 16 deletions(-) > >>> > >>> diff --git a/drivers/staging/android/sync.c > >>> b/drivers/staging/android/sync.c > >>> index dc5f382..2379f23 100644 > >>> --- a/drivers/staging/android/sync.c > >>> +++ b/drivers/staging/android/sync.c > >>> @@ -502,21 +502,22 @@ static int sync_fill_fence_info(struct fence > >>> *fence, void *data, int size) > >>> static long sync_file_ioctl_fence_info(struct sync_file *sync_file, > >>> unsigned long arg) > >>> { > >>> - struct sync_file_info *info; > >>> + struct sync_file_info in, *info; > >>> + struct sync_fence_info *fence_info = NULL; > >>> __u32 size; > >>> __u32 len = 0; > >> = 0 unneeded. > >>> int ret, i; > >>> > >>> - if (copy_from_user(&size, (void __user *)arg, sizeof(size))) > >>> + if (copy_from_user(&in, (void __user *)arg, sizeof(*info))) > >>> return -EFAULT; > >>> > >>> - if (size < sizeof(struct sync_file_info)) > >>> - return -EINVAL; > >>> + if (in.status || strcmp(in.name, "\0")) > >>> + return -EFAULT; > >> These members always get written by the fence ioctl, I'm not sure it adds > >> value to have them explicitly zero'd out by userspace. > >>> - if (size > 4096) > >>> - size = 4096; > >>> + if (in.num_fences && !in.sync_fence_info) > >>> + return -EFAULT; > >> This check is unneeded, it will happen in the copy_to_user call anyway. > >>> - info = kzalloc(size, GFP_KERNEL); > >>> + info = kzalloc(sizeof(*info), GFP_KERNEL); > >>> if (!info) > >>> return -ENOMEM; > >>> > >>> @@ -525,14 +526,33 @@ static long sync_file_ioctl_fence_info(struct > >>> sync_file *sync_file, > >>> if (info->status >= 0) > >>> info->status = !info->status; > >>> > >>> - info->num_fences = sync_file->num_fences; > >>> + /* > >>> + * Passing num_fences = 0 means that userspace want to know how > >>> + * many fences are in the sync_file to be able to allocate a buffer to > >>> + * fit all sync_fence_infos and call the ioctl again with the buffer > >>> + * assigned to info->sync_fence_info. The second call pass the > >>> + * num_fences value received in the first call. > >>> + */ > >>> + if (!in.num_fences) > >>> + goto no_fences; > >>> + > >>> + size = sync_file->num_fences * sizeof(*fence_info); > >>> + if (in.len != size) { > >>> + ret = -EFAULT; > >>> + goto out; > >>> + } > >> Maybe check for in.len < size, and set set to size? > >> > >> > >>> - len = sizeof(struct sync_file_info); > >>> + fence_info = kzalloc(size, GFP_KERNEL); > >>> + if (!fence_info) { > >>> + ret
[PATCH v6 05/11] drm/hisilicon: Add vblank driver for ADE
On 3/1/2016 3:44 PM, Xinliang Liu wrote: > Hi, > > On 1 March 2016 at 02:48, Archit Taneja wrote: >> >> >> On 2/26/2016 2:10 PM, Xinliang Liu wrote: >>> >>> Add vblank irq handle. >>> >>> v6: None. >>> v5: None. >>> v4: None. >>> v3: >>> - Remove hisi_get_crtc_from_index func. >>> - A few cleanup. >>> v2: >>> - Remove abtraction layer. >>> >>> Signed-off-by: Xinliang Liu >>> --- >>>drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c | 62 >>> + >>>drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 14 +- >>>2 files changed, 75 insertions(+), 1 deletion(-) >>> >>> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >>> b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >>> index aa2cf75cab39..749382952ab7 100644 >>> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >>> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c >>> @@ -292,6 +292,59 @@ static void ade_set_medianoc_qos(struct ade_crtc >>> *acrtc) >>> SOCKET_QOS_EN, SOCKET_QOS_EN); >>>} >>> >>> +static int ade_enable_vblank(struct drm_device *dev, unsigned int pipe) >>> +{ >>> + struct kirin_drm_private *priv = dev->dev_private; >>> + struct ade_crtc *acrtc = to_ade_crtc(priv->crtc[pipe]); >>> + struct ade_hw_ctx *ctx = acrtc->ctx; >>> + void __iomem *base = ctx->base; >>> + >>> + if (!ctx->power_on) >>> + (void)ade_power_up(ctx); >>> + >>> + ade_update_bits(base + LDI_INT_EN, FRAME_END_INT_EN_OFST, >>> + MASK(1), 1); >>> + >>> + return 0; >>> +} >>> + >>> +static void ade_disable_vblank(struct drm_device *dev, unsigned int pipe) >>> +{ >>> + struct kirin_drm_private *priv = dev->dev_private; >>> + struct ade_crtc *acrtc = to_ade_crtc(priv->crtc[pipe]); >>> + struct ade_hw_ctx *ctx = acrtc->ctx; >>> + void __iomem *base = ctx->base; >>> + >>> + if (!ctx->power_on) { >>> + DRM_ERROR("power is down! vblank disable fail\n"); >>> + return; >>> + } >>> + >>> + ade_update_bits(base + LDI_INT_EN, FRAME_END_INT_EN_OFST, >>> + MASK(1), 0); >>> +} >>> + >>> +static irqreturn_t ade_irq_handler(int irq, void *data) >>> +{ >>> + struct ade_crtc *acrtc = data; >>> + struct ade_hw_ctx *ctx = acrtc->ctx; >>> + struct drm_crtc *crtc = &acrtc->base; >>> + void __iomem *base = ctx->base; >>> + u32 status; >>> + >>> + status = readl(base + LDI_MSK_INT); >>> + DRM_DEBUG_VBL("LDI IRQ: status=0x%X\n", status); >>> + >>> + /* vblank irq */ >>> + if (status & BIT(FRAME_END_INT_EN_OFST)) { >>> + ade_update_bits(base + LDI_INT_CLR, FRAME_END_INT_EN_OFST, >>> + MASK(1), 1); >>> + drm_crtc_handle_vblank(crtc); >>> + } >>> + >>> + return IRQ_HANDLED; >>> +} >>> + >>>static void ade_display_enable(struct ade_crtc *acrtc) >>>{ >>> struct ade_hw_ctx *ctx = acrtc->ctx; >>> @@ -967,6 +1020,15 @@ int ade_drm_init(struct drm_device *dev) >>> if (ret) >>> return ret; >>> >>> + /* vblank irq init */ >>> + ret = devm_request_irq(dev->dev, ctx->irq, ade_irq_handler, >>> + DRIVER_IRQ_SHARED, dev->driver->name, >>> acrtc); >> >> >> This isn't the way we set up interrupts for kms drivers. We need to >> provide the handler in drm_driver and call drm_irq_install. > > I prefer to set up interrupts here for two reasons. > One is that it is easy to pass any interrupt private "void * data" to > the interrupt handler here. > As I discussed with Daniel Vetter before: https://lkml.org/lkml/2015/9/10/204. > > Second is setting up interrupt here in the specific SoC display > controller driver, make other SoC reuse the kirin_drm_drv.c code > easily. > Different Hisilicon SoC may has different display controller interrupts. Sure, as long as this has been discussed before. > >> >> >>> + if (ret) >>> + return ret; >>> + dev->driver->get_vblank_counter = drm_vblank_no_hw_counter; >>> + dev->driver->enable_vblank = ade_enable_vblank; >>> + dev->driver->disable_vblank = ade_disable_vblank; >>> + >>> return 0; >>>} >>> >>> diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c >>> b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c >>> index 055729c1889c..723888feb760 100644 >>> --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c >>> +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c >>> @@ -32,6 +32,7 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev) >>>{ >>> struct kirin_drm_private *priv = dev->dev_private; >>> >>> + drm_vblank_cleanup(dev); >>> dc_ops->cleanup(dev); >>> drm_mode_config_cleanup(dev); >>> devm_kfree(dev->dev, priv); >>> @@ -85,11 +86,22 @@ static int kirin_drm_kms_init(struct drm_device *dev) >>> goto err_dc_
[PATCH v6 07/11] drm/hisilicon: Add designware dsi encoder driver
On 3/1/2016 4:03 PM, Xinliang Liu wrote: > Hi, > > On 1 March 2016 at 02:49, Archit Taneja wrote: >> >> >> On 2/26/2016 2:10 PM, Xinliang Liu wrote: >>> >>> Add DesignWare MIPI DSI Host Controller v1.02 encoder driver >>> for hi6220 SoC. >>> >>> v6: >>> - Change "pclk_dsi" to "pclk". >>> v5: None. >>> v4: None. >>> v3: >>> - Rename file name to dw_drm_dsi.c >>> - Make encoder type as DRM_MODE_ENCODER_DSI. >>> - A few cleanup. >>> v2: >>> - Remove abtraction layer. >>> >>> Signed-off-by: Xinliang Liu >>> Signed-off-by: Xinwei Kong >>> Signed-off-by: Andy Green >>> --- >>>drivers/gpu/drm/hisilicon/kirin/Kconfig | 1 + >>>drivers/gpu/drm/hisilicon/kirin/Makefile | 3 +- >>>drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c | 743 >>> +++ >>>drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h | 83 +++ >>>4 files changed, 829 insertions(+), 1 deletion(-) >>>create mode 100644 drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >>>create mode 100644 drivers/gpu/drm/hisilicon/kirin/dw_dsi_reg.h >>> >>> diff --git a/drivers/gpu/drm/hisilicon/kirin/Kconfig >>> b/drivers/gpu/drm/hisilicon/kirin/Kconfig >>> index 3ac4b8edeac1..de0d454c5c13 100644 >>> --- a/drivers/gpu/drm/hisilicon/kirin/Kconfig >>> +++ b/drivers/gpu/drm/hisilicon/kirin/Kconfig >>> @@ -4,6 +4,7 @@ config DRM_HISI_KIRIN >>> select DRM_KMS_HELPER >>> select DRM_GEM_CMA_HELPER >>> select DRM_KMS_CMA_HELPER >>> + select DRM_MIPI_DSI >>> help >>>Choose this option if you have a hisilicon Kirin >>> chipsets(hi6220). >>>If M is selected the module will be called kirin-drm. >>> diff --git a/drivers/gpu/drm/hisilicon/kirin/Makefile >>> b/drivers/gpu/drm/hisilicon/kirin/Makefile >>> index 2a61ab006ddb..5dcd0d4328b6 100644 >>> --- a/drivers/gpu/drm/hisilicon/kirin/Makefile >>> +++ b/drivers/gpu/drm/hisilicon/kirin/Makefile >>> @@ -1,4 +1,5 @@ >>>kirin-drm-y := kirin_drm_drv.o \ >>> - kirin_drm_ade.o >>> + kirin_drm_ade.o \ >>> + dw_drm_dsi.o >>> >>>obj-$(CONFIG_DRM_HISI_KIRIN) += kirin-drm.o >>> diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >>> b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >>> new file mode 100644 >>> index ..8329148cc89d >>> --- /dev/null >>> +++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c >>> @@ -0,0 +1,743 @@ >>> +/* >>> + * DesignWare MIPI DSI Host Controller v1.02 driver >>> + * >>> + * Copyright (c) 2016 Linaro Limited. >>> + * Copyright (c) 2014-2016 Hisilicon Limited. >>> + * >>> + * Author: >>> + * Xinliang Liu >>> + * Xinliang Liu >>> + * Xinwei Kong >>> + * >>> + * This program is free software; you can redistribute it and/or modify >>> + * it under the terms of the GNU General Public License version 2 as >>> + * published by the Free Software Foundation. >>> + * >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include "dw_dsi_reg.h" >>> + >>> +#define MAX_TX_ESC_CLK(10) >>> +#define ROUND(x, y) ((x) / (y) + ((x) % (y) * 10 / (y) >= 5 ? 1 : 0)) >>> +#define PHY_REF_CLK_RATE 1920 >>> +#define PHY_REF_CLK_PERIOD_PS (10 / (PHY_REF_CLK_RATE / 1000)) >>> + >>> +#define encoder_to_dsi(encoder) \ >>> + container_of(encoder, struct dw_dsi, encoder) >>> +#define host_to_dsi(host) \ >>> + container_of(host, struct dw_dsi, host) >>> + >>> +struct mipi_phy_params { >>> + u32 clk_t_lpx; >>> + u32 clk_t_hs_prepare; >>> + u32 clk_t_hs_zero; >>> + u32 clk_t_hs_trial; >>> + u32 clk_t_wakeup; >>> + u32 data_t_lpx; >>> + u32 data_t_hs_prepare; >>> + u32 data_t_hs_zero; >>> + u32 data_t_hs_trial; >>> + u32 data_t_ta_go; >>> + u32 data_t_ta_get; >>> + u32 data_t_wakeup; >>> + u32 hstx_ckg_sel; >>> + u32 pll_fbd_div5f; >>> + u32 pll_fbd_div1f; >>> + u32 pll_fbd_2p; >>> + u32 pll_enbwt; >>> + u32 pll_fbd_p; >>> + u32 pll_fbd_s; >>> + u32 pll_pre_div1p; >>> + u32 pll_pre_p; >>> + u32 pll_vco_750M; >>> + u32 pll_lpf_rs; >>> + u32 pll_lpf_cs; >>> + u32 clklp2hs_time; >>> + u32 clkhs2lp_time; >>> + u32 lp2hs_time; >>> + u32 hs2lp_time; >>> + u32 clk_to_data_delay; >>> + u32 data_to_clk_delay; >>> + u32 lane_byte_clk_kHz; >>> + u32 clk_division; >>> +}; >>> + >>> +struct dsi_hw_ctx { >>> + void __iomem *base; >>> + struct clk *pclk; >>> +}; >>> + >>> +struct dw_dsi { >>> + struct drm_encoder encoder; >>> + struct drm_display_mode cur_mode; >>> + struct dsi_hw_ctx *ctx; >>> + struct mipi_phy_params phy; >>> + >>> + u32 lanes; >>> + enum mipi_dsi_pixel_format format; >>> + unsigned long mode_flags; >>> + bool enable; >>> +}; >>> + >>> +struct dsi_data { >>> + struct dw_
[PATCH v5 1/5] staging/android: add num_fences field to struct sync_file_info
From: Gustavo Padovan Inform userspace how many fences are in the sync_fence_info field. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst --- drivers/staging/android/sync.c | 2 ++ drivers/staging/android/uapi/sync.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 3a8f210..31aa462 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -525,6 +525,8 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (info->status >= 0) info->status = !info->status; + info->num_fences = sync_file->num_fences; + len = sizeof(struct sync_file_info); for (i = 0; i < sync_file->num_fences; ++i) { diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index a0cf357..4ffb7cc 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -47,12 +47,14 @@ struct sync_fence_info { * userspace including pt_info. * @name: name of fence * @status:status of fence. 1: signaled 0:active <0:error + * @num_fences number of fences in the sync_file * @sync_fence_info: array of sync_fence_info for every fence in the sync_file */ struct sync_file_info { __u32 len; charname[32]; __s32 status; + __u32 num_fences; __u8sync_fence_info[0]; }; -- 2.5.0
[PATCH v5 2/5] staging/android: rename SYNC_IOC_FENCE_INFO
From: Gustavo Padovan We don't use the 'fence' name to refer to sync_file anymore. So rename it to SYNC_IOC_FILE_INFO. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst --- drivers/staging/android/sync.c | 2 +- drivers/staging/android/uapi/sync.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 31aa462..dc5f382 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -562,7 +562,7 @@ static long sync_file_ioctl(struct file *file, unsigned int cmd, case SYNC_IOC_MERGE: return sync_file_ioctl_merge(sync_file, arg); - case SYNC_IOC_FENCE_INFO: + case SYNC_IOC_FILE_INFO: return sync_file_ioctl_fence_info(sync_file, arg); default: diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index 4ffb7cc..dd0dd84 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -81,6 +81,6 @@ struct sync_file_info { * pt_info is a buffer containing sync_pt_infos for every sync_pt in the fence. * To iterate over the sync_pt_infos, use the sync_pt_info.len field. */ -#define SYNC_IOC_FENCE_INFO_IOWR(SYNC_IOC_MAGIC, 2, struct sync_file_info) +#define SYNC_IOC_FILE_INFO _IOWR(SYNC_IOC_MAGIC, 2, struct sync_file_info) #endif /* _UAPI_LINUX_SYNC_H */ -- 2.5.0
[PATCH v5 3/5] staging/android: remove redundant comments on sync_merge_data
From: Gustavo Padovan struct sync_merge_data already have documentation on top of the struct definition. No need to duplicate it. Signed-off-by: Gustavo Padovan Reviewed-by: Maarten Lankhorst --- drivers/staging/android/uapi/sync.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index dd0dd84..f0b41ce 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -21,9 +21,9 @@ * @fence: returns the fd of the new fence to userspace */ struct sync_merge_data { - __s32 fd2; /* fd of second fence */ - charname[32]; /* name of new fence */ - __s32 fence; /* fd on newly created fence */ + __s32 fd2; + charname[32]; + __s32 fence; }; /** -- 2.5.0
[PATCH v5 4/5] staging/android: refactor SYNC_IOC_FILE_INFO
From: Gustavo Padovan Change SYNC_IOC_FILE_INFO behaviour to avoid future API breaks and optimize buffer Now num_fences can be filled by the caller to inform how many fences it wants to retrieve from the kernel. If the num_fences passed is greater than zero info->sync_fence_info should point to a buffer with enough space to fit all fences. However if num_fences passed to the kernel is 0, the kernel will reply with number of fences of the sync_file. Sending first an ioctl with num_fences = 0 can optimize buffer allocation, in a first call with num_fences = 0 userspace will receive the actual number of fences in the num_fences filed. Then it can allocate a buffer with the correct size on sync_fence_info and call SYNC_IOC_FILE_INFO again, but now with the actual value of num_fences in the sync_file. Also, info->sync_fence_info was converted to __u64 pointer to prevent 32bit compatibility issues. An example userspace code for the later would be: struct sync_file_info *info; int err, size, num_fences; info = malloc(sizeof(*info)); info.flags = 0; err = ioctl(fd, SYNC_IOC_FILE_INFO, info); num_fences = info->num_fences; if (num_fences) { info.flags = 0; size = sizeof(struct sync_fence_info) * num_fences; info->num_fences = num_fences; info->sync_fence_info = (uint64_t) calloc(num_fences, sizeof(struct sync_fence_info)); err = ioctl(fd, SYNC_IOC_FILE_INFO, info); } v2: fix fence_info memory leak v3: Comments from Emil Velikov - improve commit message - remove __u64 cast - remove check for output fields in file_info - clean up sync_fill_fence_info() Comments from Maarten Lankhorst - remove in.num_fences && !in.sync_fence_info check - remove info->len and use only num_fences to calculate size Comments from Dan Carpenter - fix info->sync_fence_info documentation Signed-off-by: Gustavo Padovan --- drivers/staging/android/sync.c | 64 - drivers/staging/android/uapi/sync.h | 9 ++ 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index dc5f382..3604e453 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -479,13 +479,9 @@ err_put_fd: return err; } -static int sync_fill_fence_info(struct fence *fence, void *data, int size) +static void sync_fill_fence_info(struct fence *fence, + struct sync_fence_info *info) { - struct sync_fence_info *info = data; - - if (size < sizeof(*info)) - return -ENOMEM; - strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), sizeof(info->obj_name)); strlcpy(info->driver_name, fence->ops->get_driver_name(fence), @@ -495,28 +491,20 @@ static int sync_fill_fence_info(struct fence *fence, void *data, int size) else info->status = 0; info->timestamp_ns = ktime_to_ns(fence->timestamp); - - return sizeof(*info); } static long sync_file_ioctl_fence_info(struct sync_file *sync_file, unsigned long arg) { - struct sync_file_info *info; + struct sync_file_info in, *info; + struct sync_fence_info *fence_info = NULL; __u32 size; - __u32 len = 0; int ret, i; - if (copy_from_user(&size, (void __user *)arg, sizeof(size))) + if (copy_from_user(&in, (void __user *)arg, sizeof(in))) return -EFAULT; - if (size < sizeof(struct sync_file_info)) - return -EINVAL; - - if (size > 4096) - size = 4096; - - info = kzalloc(size, GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; @@ -525,29 +513,47 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (info->status >= 0) info->status = !info->status; - info->num_fences = sync_file->num_fences; - - len = sizeof(struct sync_file_info); + /* +* Passing num_fences = 0 means that userspace doesn't want to +* retrieve any sync_fence_info. If num_fences = 0 we skip filling +* sync_fence_info and return the actual number of fences on +* info->num_fences. +*/ + if (!in.num_fences) + goto no_fences; - for (i = 0; i < sync_file->num_fences; ++i) { - struct fence *fence = sync_file->cbs[i].fence; + if (in.num_fences < sync_file->num_fences) { + ret = -EINVAL; + goto out; + } - ret = sync_fill_fence_info(fence, (u8 *)info + len, size - len); + size = sync_file->num_fences * sizeof(*fenc
[PATCH v5 5/5] staging/android: add flags member to sync ioctl structs
From: Gustavo Padovan Play safe and add flags member to all structs. So we don't need to break API or create new IOCTL in the future if new features that requires flags arises. v2: check if flags are valid (zero, in this case) v3: return -EINVAL if flags are not zero'ed Signed-off-by: Gustavo Padovan --- drivers/staging/android/sync.c | 8 drivers/staging/android/uapi/sync.h | 6 ++ 2 files changed, 14 insertions(+) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 3604e453..3c265ed 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -445,6 +445,11 @@ static long sync_file_ioctl_merge(struct sync_file *sync_file, goto err_put_fd; } + if (data.flags) { + err = -EINVAL; + goto err_put_fd; + } + fence2 = sync_file_fdget(data.fd2); if (!fence2) { err = -ENOENT; @@ -504,6 +509,9 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (copy_from_user(&in, (void __user *)arg, sizeof(in))) return -EFAULT; + if (in.flags) + return -EINVAL; + info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; diff --git a/drivers/staging/android/uapi/sync.h b/drivers/staging/android/uapi/sync.h index a122bb5..11e2d28 100644 --- a/drivers/staging/android/uapi/sync.h +++ b/drivers/staging/android/uapi/sync.h @@ -19,11 +19,13 @@ * @fd2: file descriptor of second fence * @name: name of new fence * @fence: returns the fd of the new fence to userspace + * @flags: merge_data flags */ struct sync_merge_data { __s32 fd2; charname[32]; __s32 fence; + __u32 flags; }; /** @@ -31,12 +33,14 @@ struct sync_merge_data { * @obj_name: name of parent sync_timeline * @driver_name: name of driver implementing the parent * @status:status of the fence 0:active 1:signaled <0:error + * @flags: fence_info flags * @timestamp_ns: timestamp of status change in nanoseconds */ struct sync_fence_info { charobj_name[32]; chardriver_name[32]; __s32 status; + __u32 flags; __u64 timestamp_ns; }; @@ -44,6 +48,7 @@ struct sync_fence_info { * struct sync_file_info - data returned from fence info ioctl * @name: name of fence * @status:status of fence. 1: signaled 0:active <0:error + * @flags: sync_file_info flags * @num_fences number of fences in the sync_file * @sync_fence_info: pointer to array of structs sync_fence_info with all * fences in the sync_file @@ -51,6 +56,7 @@ struct sync_fence_info { struct sync_file_info { charname[32]; __s32 status; + __u32 flags; __u32 num_fences; __u64 sync_fence_info; -- 2.5.0
[PATCH v2.1 3/6] drm/atomic: Always call steal_encoder, v2.
There's no need to have a separate function to get the crtc which is stolen, this can already be found when actually stealing the encoder. drm_for_each_connector already checks for connection_mutex, so use that macro now. Changes since v1: - Do not check for NULL crtc in connector_state, this may happen when a crtc is disabled and its encoder stolen. - Because of this, use connector->state->crtc instead of conn_state->crtc. Signed-off-by: Maarten Lankhorst --- Oops, this patch had a WARN_ON(!conn_state->crtc); in v1, this broke DP MST which had a legitimate reason to do so. diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 3d1f97a832fc..72ca85b32260 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -106,25 +106,6 @@ check_pending_encoder_assignment(struct drm_atomic_state *state, return true; } -static struct drm_crtc * -get_current_crtc_for_encoder(struct drm_device *dev, -struct drm_encoder *encoder) -{ - struct drm_mode_config *config = &dev->mode_config; - struct drm_connector *connector; - - WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); - - drm_for_each_connector(connector, dev) { - if (connector->state->best_encoder != encoder) - continue; - - return connector->state->crtc; - } - - return NULL; -} - static void set_best_encoder(struct drm_atomic_state *state, struct drm_connector_state *conn_state, @@ -168,38 +149,18 @@ set_best_encoder(struct drm_atomic_state *state, static int steal_encoder(struct drm_atomic_state *state, - struct drm_encoder *encoder, - struct drm_crtc *encoder_crtc) + struct drm_encoder *encoder) { - struct drm_mode_config *config = &state->dev->mode_config; struct drm_crtc_state *crtc_state; struct drm_connector *connector; struct drm_connector_state *connector_state; - /* -* We can only steal an encoder coming from a connector, which means we -* must already hold the connection_mutex. -*/ - WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); - - DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", -encoder->base.id, encoder->name, -encoder_crtc->base.id, encoder_crtc->name); + drm_for_each_connector(connector, state->dev) { + struct drm_crtc *encoder_crtc; - crtc_state = drm_atomic_get_crtc_state(state, encoder_crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - - crtc_state->connectors_changed = true; - - list_for_each_entry(connector, &config->connector_list, head) { if (connector->state->best_encoder != encoder) continue; - DRM_DEBUG_ATOMIC("Stealing encoder from [CONNECTOR:%d:%s]\n", -connector->base.id, -connector->name); - connector_state = drm_atomic_get_connector_state(state, connector); if (IS_ERR(connector_state)) @@ -208,7 +169,18 @@ steal_encoder(struct drm_atomic_state *state, if (connector_state->best_encoder != encoder) continue; + encoder_crtc = connector->state->crtc; + + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", +encoder->base.id, encoder->name, +encoder_crtc->base.id, encoder_crtc->name); + set_best_encoder(state, connector_state, NULL); + + crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc); + crtc_state->connectors_changed = true; + + return 0; } return 0; @@ -221,7 +193,6 @@ update_connector_routing(struct drm_atomic_state *state, { const struct drm_connector_helper_funcs *funcs; struct drm_encoder *new_encoder; - struct drm_crtc *encoder_crtc; struct drm_crtc_state *crtc_state; int idx, ret; @@ -299,17 +270,12 @@ update_connector_routing(struct drm_atomic_state *state, return -EINVAL; } - encoder_crtc = get_current_crtc_for_encoder(state->dev, - new_encoder); - - if (encoder_crtc) { - ret = steal_encoder(state, new_encoder, encoder_crtc); - if (ret) { - DRM_DEBUG_ATOMIC("Encoder stealing failed for [CONNECTOR:%d:%s]\n", -connector->base.id, -connector->name); - return ret; - } + ret = ste
Alternative binding proposal for tda998x audio (Was: Re: [PATCH RFC v5 4/8] drm/i2c: tda998x: Add support of a DT graph of ports)
Ok, here is just one more simple alternative for tda998x audio binding. I feel that the graph ports binding for audio does not make sense without a graph based ASoC machine driver implementation. The ASoC simple-card is already here and it so widely used that there is no getting rid of that any time soon. This proposal provides the same functionality as the patch in the root of this thread, but in a simpler way and is equally compatible with simple-card. The example assumes a dt-include file with integer definitions for TDA998x_SPDIF and TDA998x_I2S. tda19988 { compatible = "nxp,tda998x"; reg = <0x70>; pinctrl-names = "default", "off"; pinctrl-0 = <&nxp_hdmi_bonelt_pins>; pinctrl-1 = <&nxp_hdmi_bonelt_off_pins>; video-ports = <0x230145>; /* Required by simple-card. The number of sound-dai cells must agree with the number of audio ports described in audio-ports property. */ #sound-dai-cells = <2>; /* DAI-format AP_ENA reg value */ audio-ports = < TDA998x_SPDIF 0x04 TDA998x_I2S 0x03>; port { hdmi_0: endpoint at 0 { remote-endpoint = <&lcdc_0>; }; }; }; Russell, Rob? Which one would you prefer, the old graph ports binding or this simpler version? Best regards, Jyri
[PATCH v2 1/6] drm/atomic: Clean up update_output_state.
On Wed, Feb 24, 2016 at 09:37:28AM +0100, Maarten Lankhorst wrote: > With the addition of crtc_state->connector_mask other connectors from > different crtc's aren't needed any more to determine if a crtc has > connectors, so only call add_affected_connectors on the target crtc. > This allows a cleanup to first remove all current connectors, then > add all set->connectors to the target crtc. The new order of things make sense to me. Reviewed-by: Ville Syrjälä One thing I did notice is that we're not clearing the primary plane crtc and fb when a crtc gets disabled due to its connector(s) getting stolen. We do clear them when the crtc is explicitly disabled. Not sure if that matters for anything, but it does seem a bit inconsistent. > > Signed-off-by: Maarten Lankhorst > --- > drivers/gpu/drm/drm_atomic_helper.c | 41 > +++-- > 1 file changed, 17 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > b/drivers/gpu/drm/drm_atomic_helper.c > index 4da4f2a49078..a0226d4b949a 100644 > --- a/drivers/gpu/drm/drm_atomic_helper.c > +++ b/drivers/gpu/drm/drm_atomic_helper.c > @@ -1761,28 +1761,18 @@ static int update_output_state(struct > drm_atomic_state *state, > struct drm_crtc_state *crtc_state; > struct drm_connector *connector; > struct drm_connector_state *conn_state; > - int ret, i, j; > + int ret, i; > > ret = drm_modeset_lock(&dev->mode_config.connection_mutex, > state->acquire_ctx); > if (ret) > return ret; > > - /* First grab all affected connector/crtc states. */ > - for (i = 0; i < set->num_connectors; i++) { > - conn_state = drm_atomic_get_connector_state(state, > - set->connectors[i]); > - if (IS_ERR(conn_state)) > - return PTR_ERR(conn_state); > - } > - > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > - ret = drm_atomic_add_affected_connectors(state, crtc); > - if (ret) > - return ret; > - } > + /* First disable all connectors on the target crtc. */ > + ret = drm_atomic_add_affected_connectors(state, set->crtc); > + if (ret) > + return ret; > > - /* Then recompute connector->crtc links and crtc enabling state. */ > for_each_connector_in_state(state, connector, conn_state, i) { > if (conn_state->crtc == set->crtc) { > ret = drm_atomic_set_crtc_for_connector(conn_state, > @@ -1790,16 +1780,19 @@ static int update_output_state(struct > drm_atomic_state *state, > if (ret) > return ret; > } > + } > > - for (j = 0; j < set->num_connectors; j++) { > - if (set->connectors[j] == connector) { > - ret = > drm_atomic_set_crtc_for_connector(conn_state, > - > set->crtc); > - if (ret) > - return ret; > - break; > - } > - } > + /* Then set all connectors from set->connectors on the target crtc */ > + for (i = 0; i < set->num_connectors; i++) { > + conn_state = drm_atomic_get_connector_state(state, > + set->connectors[i]); > + if (IS_ERR(conn_state)) > + return PTR_ERR(conn_state); > + > + ret = drm_atomic_set_crtc_for_connector(conn_state, > + set->crtc); > + if (ret) > + return ret; > } > > for_each_crtc_in_state(state, crtc, crtc_state, i) { > -- > 2.1.0 > > ___ > dri-devel mailing list > dri-devel at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Ville Syrjälä Intel OTC
[Intel-gfx] [PATCH v2 2/6] drm/atomic: Pass connector and state to update_connector_routing.
On Wed, Feb 24, 2016 at 09:37:29AM +0100, Maarten Lankhorst wrote: > Minor cleanup, connector and connector_state are always non-NULL here. > > Signed-off-by: Maarten Lankhorst Reviewed-by: Ville Syrjälä > --- > drivers/gpu/drm/drm_atomic_helper.c | 15 +-- > 1 file changed, 5 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > b/drivers/gpu/drm/drm_atomic_helper.c > index a0226d4b949a..3d1f97a832fc 100644 > --- a/drivers/gpu/drm/drm_atomic_helper.c > +++ b/drivers/gpu/drm/drm_atomic_helper.c > @@ -215,22 +215,16 @@ steal_encoder(struct drm_atomic_state *state, > } > > static int > -update_connector_routing(struct drm_atomic_state *state, int conn_idx) > +update_connector_routing(struct drm_atomic_state *state, > + struct drm_connector *connector, > + struct drm_connector_state *connector_state) > { > const struct drm_connector_helper_funcs *funcs; > struct drm_encoder *new_encoder; > struct drm_crtc *encoder_crtc; > - struct drm_connector *connector; > - struct drm_connector_state *connector_state; > struct drm_crtc_state *crtc_state; > int idx, ret; > > - connector = state->connectors[conn_idx]; > - connector_state = state->connector_states[conn_idx]; > - > - if (!connector) > - return 0; > - > DRM_DEBUG_ATOMIC("Updating routing for [CONNECTOR:%d:%s]\n", >connector->base.id, >connector->name); > @@ -494,7 +488,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev, >* drivers must set crtc->mode_changed themselves when connector >* properties need to be updated. >*/ > - ret = update_connector_routing(state, i); > + ret = update_connector_routing(state, connector, > +connector_state); > if (ret) > return ret; > } > -- > 2.1.0 > > ___ > Intel-gfx mailing list > Intel-gfx at lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Ville Syrjälä Intel OTC
[PATCH v12 00/14] MT8173 DRM support
Hi, another round of the MT8173 DRM driver. I plan to send a pull request with this version soon, there are just some small changes to the main driver patch: Changes since v11: - Instead of disabling all planes initally, configure them according to their state. This way the plane doesn't stay disabled until the first flip (which may never happen). - Disable the pipe instead of crashing if any of its components are disabled or missing in the device tree. - Correct parameter type in the mtk_drm_gem_create() declaration regards Philipp CK Hu (5): dt-bindings: drm/mediatek: Add Mediatek display subsystem dts binding drm/mediatek: Add DRM Driver for Mediatek SoC MT8173. drm/mediatek: Add DSI sub driver arm64: dts: mt8173: Add display subsystem related nodes arm64: dts: mt8173: Add HDMI related nodes Jie Qiu (3): drm/mediatek: Add DPI sub driver drm/mediatek: Add HDMI support drm/mediatek: enable hdmi output control bit Philipp Zabel (6): dt-bindings: drm/mediatek: Add Mediatek HDMI dts binding clk: mediatek: make dpi0_sel propagate rate changes clk: mediatek: Add hdmi_ref HDMI PHY PLL reference clock output dt-bindings: hdmi-connector: add DDC I2C bus phandle documentation clk: mediatek: remove hdmitx_dig_cts from TOP clocks arm64: dts: mt8173-evb: enable HDMI output .../bindings/display/connector/hdmi-connector.txt | 1 + .../bindings/display/mediatek/mediatek,disp.txt| 203 + .../bindings/display/mediatek/mediatek,dpi.txt | 35 + .../bindings/display/mediatek/mediatek,dsi.txt | 60 ++ .../bindings/display/mediatek/mediatek,hdmi.txt| 148 arch/arm64/boot/dts/mediatek/mt8173-evb.dts| 38 + arch/arm64/boot/dts/mediatek/mt8173.dtsi | 304 +++ drivers/clk/mediatek/clk-mt8173.c | 12 +- drivers/clk/mediatek/clk-mtk.h | 15 +- drivers/gpu/drm/Kconfig| 2 + drivers/gpu/drm/Makefile | 1 + drivers/gpu/drm/mediatek/Kconfig | 21 + drivers/gpu/drm/mediatek/Makefile | 23 + drivers/gpu/drm/mediatek/mtk_cec.c | 245 ++ drivers/gpu/drm/mediatek/mtk_cec.h | 25 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c| 302 +++ drivers/gpu/drm/mediatek/mtk_disp_rdma.c | 240 ++ drivers/gpu/drm/mediatek/mtk_dpi.c | 757 + drivers/gpu/drm/mediatek/mtk_dpi.h | 85 ++ drivers/gpu/drm/mediatek/mtk_dpi_regs.h| 228 + drivers/gpu/drm/mediatek/mtk_drm_crtc.c| 582 + drivers/gpu/drm/mediatek/mtk_drm_crtc.h| 32 + drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 355 drivers/gpu/drm/mediatek/mtk_drm_ddp.h | 41 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c| 225 + drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h| 150 drivers/gpu/drm/mediatek/mtk_drm_drv.c | 583 + drivers/gpu/drm/mediatek/mtk_drm_drv.h | 56 ++ drivers/gpu/drm/mediatek/mtk_drm_fb.c | 165 drivers/gpu/drm/mediatek/mtk_drm_fb.h | 23 + drivers/gpu/drm/mediatek/mtk_drm_gem.c | 266 ++ drivers/gpu/drm/mediatek/mtk_drm_gem.h | 59 ++ drivers/gpu/drm/mediatek/mtk_drm_hdmi_drv.c| 579 + drivers/gpu/drm/mediatek/mtk_drm_plane.c | 240 ++ drivers/gpu/drm/mediatek/mtk_drm_plane.h | 59 ++ drivers/gpu/drm/mediatek/mtk_dsi.c | 942 + drivers/gpu/drm/mediatek/mtk_hdmi.c| 479 +++ drivers/gpu/drm/mediatek/mtk_hdmi.h| 221 + drivers/gpu/drm/mediatek/mtk_hdmi_ddc_drv.c| 362 drivers/gpu/drm/mediatek/mtk_hdmi_hw.c | 664 +++ drivers/gpu/drm/mediatek/mtk_hdmi_hw.h | 73 ++ drivers/gpu/drm/mediatek/mtk_hdmi_regs.h | 222 + drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 487 +++ drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c | 505 +++ include/dt-bindings/clock/mt8173-clk.h | 3 +- 45 files changed, 10113 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt create mode 100644 drivers/gpu/drm/mediatek/Kconfig create mode 100644 drivers/gpu/drm/mediatek/Makefile create mode 100644 drivers/gpu/drm/mediatek/mtk_cec.c create mode 100644 drivers/gpu/drm/mediatek/mtk_cec.h create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.c create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_rdma.c create mode 10064
[PATCH v12 01/14] dt-bindings: drm/mediatek: Add Mediatek display subsystem dts binding
From: CK Hu Add device tree binding documentation for the display subsystem in Mediatek MT8173 SoCs. Signed-off-by: CK Hu Signed-off-by: Philipp Zabel Acked-by: Rob Herring --- .../bindings/display/mediatek/mediatek,disp.txt| 203 + .../bindings/display/mediatek/mediatek,dpi.txt | 35 .../bindings/display/mediatek/mediatek,dsi.txt | 60 ++ 3 files changed, 298 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt new file mode 100644 index 000..db6e77e --- /dev/null +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,disp.txt @@ -0,0 +1,203 @@ +Mediatek display subsystem +== + +The Mediatek display subsystem consists of various DISP function blocks in the +MMSYS register space. The connections between them can be configured by output +and input selectors in the MMSYS_CONFIG register space. Pixel clock and start +of frame signal are distributed to the other function blocks by a DISP_MUTEX +function block. + +All DISP device tree nodes must be siblings to the central MMSYS_CONFIG node. +For a description of the MMSYS_CONFIG binding, see +Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt. + +DISP function blocks + + +A display stream starts at a source function block that reads pixel data from +memory and ends with a sink function block that drives pixels on a display +interface, or writes pixels back to memory. All DISP function blocks have +their own register space, interrupt, and clock gate. The blocks that can +access memory additionally have to list the IOMMU and local arbiter they are +connected to. + +For a description of the display interface sink function blocks, see +Documentation/devicetree/bindings/display/mediatek/mediatek,dsi.txt and +Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.txt. + +Required properties (all function blocks): +- compatible: "mediatek,-disp-", one of + "mediatek,-disp-ovl" - overlay (4 layers, blending, csc) + "mediatek,-disp-rdma" - read DMA / line buffer + "mediatek,-disp-wdma" - write DMA + "mediatek,-disp-color" - color processor + "mediatek,-disp-aal" - adaptive ambient light controller + "mediatek,-disp-gamma" - gamma correction + "mediatek,-disp-merge" - merge streams from two RDMA sources + "mediatek,-disp-split" - split stream to two encoders + "mediatek,-disp-ufoe" - data compression engine + "mediatek,-dsi"- DSI controller, see mediatek,dsi.txt + "mediatek,-dpi"- DPI controller, see mediatek,dpi.txt + "mediatek,-disp-mutex" - display mutex + "mediatek,-disp-od"- overdrive +- reg: Physical base address and length of the function block register space +- interrupts: The interrupt signal from the function block (required, except for + merge and split function blocks). +- clocks: device clocks + See Documentation/devicetree/bindings/clock/clock-bindings.txt for details. + For most function blocks this is just a single clock input. Only the DSI and + DPI controller nodes have multiple clock inputs. These are documented in + mediatek,dsi.txt and mediatek,dpi.txt, respectively. + +Required properties (DMA function blocks): +- compatible: Should be one of + "mediatek,-disp-ovl" + "mediatek,-disp-rdma" + "mediatek,-disp-wdma" +- larb: Should contain a phandle pointing to the local arbiter device as defined + in Documentation/devicetree/bindings/soc/mediatek/mediatek,smi-larb.txt +- iommus: Should point to the respective IOMMU block with master port as + argument, see Documentation/devicetree/bindings/iommu/mediatek,iommu.txt + for details. + +Examples: + +mmsys: clock-controller at 1400 { + compatible = "mediatek,mt8173-mmsys", "syscon"; + reg = <0 0x1400 0 0x1000>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + #clock-cells = <1>; +}; + +ovl0: ovl at 1400c000 { + compatible = "mediatek,mt8173-disp-ovl"; + reg = <0 0x1400c000 0 0x1000>; + interrupts = ; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + clocks = <&mmsys CLK_MM_DISP_OVL0>; + iommus = <&iommu M4U_PORT_DISP_OVL0>; + mediatek,larb = <&larb0>; +}; + +ovl1: ovl at 1400d000 { + compatible = "mediatek,mt8173-disp-ovl"; + reg = <0 0x1400d000 0 0x1000>; + interrupts = ; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + clocks = <&mmsys CLK_MM_DISP_OVL1>; + iommus = <&iommu M4U_PORT_DISP_OVL1>; + mediatek,larb = <&larb4>; +}; + +rdma0: rdma
[PATCH v12 09/14] arm64: dts: mt8173: Add HDMI related nodes
From: CK Hu This patch adds the device nodes for the HDMI encoder, HDMI PHY, and HDMI CEC modules. Signed-off-by: CK Hu Signed-off-by: Cawa Cheng Signed-off-by: Jie Qiu Signed-off-by: Daniel Kurtz Signed-off-by: Philipp Zabel --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 69 1 file changed, 69 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 4ff666d..9fb32a1 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -199,6 +199,16 @@ , ; + hdmi_pin: xxx { + + /*hdmi htplg pin*/ + pins1 { + pinmux = ; + input-enable; + bias-pull-down; + }; + }; + i2c0_pins_a: i2c0 { pins1 { pinmux = , @@ -286,6 +296,14 @@ clock-names = "spi", "wrap"; }; + cec: cec at 10013000 { + compatible = "mediatek,mt8173-cec"; + reg = <0 0x10013000 0 0xbc>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_CEC>; + status = "disabled"; + }; + sysirq: intpol-controller at 10200620 { compatible = "mediatek,mt8173-sysirq", "mediatek,mt6577-sysirq"; @@ -312,6 +330,19 @@ #clock-cells = <1>; }; + hdmi_phy: hdmi-phy at 10209100 { + compatible = "mediatek,mt8173-hdmi-phy"; + reg = <0 0x10209100 0 0x24>; + clocks = <&apmixedsys CLK_APMIXED_HDMI_REF>; + clock-names = "pll_ref"; + clock-output-names = "hdmitx_dig_cts"; + mediatek,ibias = <0xa>; + mediatek,ibias_up = <0x1c>; + #clock-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + mipi_tx0: mipi-dphy at 10215000 { compatible = "mediatek,mt8173-mipi-tx"; reg = <0 0x10215000 0 0x1000>; @@ -798,6 +829,12 @@ <&apmixedsys CLK_APMIXED_TVDPLL>; clock-names = "pixel", "engine", "pll"; status = "disabled"; + + port { + dpi0_out: endpoint { + remote-endpoint = <&hdmi0_in>; + }; + }; }; pwm0: pwm at 1401e000 { @@ -855,6 +892,38 @@ clocks = <&mmsys CLK_MM_DISP_OD>; }; + hdmi0: hdmi at 14025000 { + compatible = "mediatek,mt8173-hdmi"; + reg = <0 0x14025000 0 0x400>; + interrupts = ; + clocks = <&mmsys CLK_MM_HDMI_PIXEL>, +<&mmsys CLK_MM_HDMI_PLLCK>, +<&mmsys CLK_MM_HDMI_AUDIO>, +<&mmsys CLK_MM_HDMI_SPDIF>; + clock-names = "pixel", "pll", "bclk", "spdif"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_pin>; + phys = <&hdmi_phy>; + phy-names = "hdmi"; + mediatek,syscon-hdmi = <&mmsys 0x900>; + assigned-clocks = <&topckgen CLK_TOP_HDMI_SEL>; + assigned-clock-parents = <&hdmi_phy>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port at 0 { + reg = <0>; + + hdmi0_in: endpoint { + remote-endpoint = <&dpi0_out>; + }; + }; + }; + }; + larb4: larb at 14027000 { compatible = "mediatek,mt8173-smi-larb"; reg = <0 0x14027000 0 0x1000>; -- 2.7.0
[PATCH v12 05/14] dt-bindings: drm/mediatek: Add Mediatek HDMI dts binding
Add the device tree binding documentation for Mediatek HDMI, HDMI PHY and HDMI DDC devices. Signed-off-by: Philipp Zabel Acked-by: Rob Herring --- .../bindings/display/mediatek/mediatek,hdmi.txt| 148 + 1 file changed, 148 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt new file mode 100644 index 000..7b12424 --- /dev/null +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,hdmi.txt @@ -0,0 +1,148 @@ +Mediatek HDMI Encoder += + +The Mediatek HDMI encoder can generate HDMI 1.4a or MHL 2.0 signals from +its parallel input. + +Required properties: +- compatible: Should be "mediatek,-hdmi". +- reg: Physical base address and length of the controller's registers +- interrupts: The interrupt signal from the function block. +- clocks: device clocks + See Documentation/devicetree/bindings/clock/clock-bindings.txt for details. +- clock-names: must contain "pixel", "pll", "bclk", and "spdif". +- phys: phandle link to the HDMI PHY node. + See Documentation/devicetree/bindings/phy/phy-bindings.txt for details. +- phy-names: must contain "hdmi" +- mediatek,syscon-hdmi: phandle link and register offset to the system + configuration registers. For mt8173 this must be offset 0x900 into the + MMSYS_CONFIG region: <&mmsys 0x900>. +- ports: A node containing input and output port nodes with endpoint + definitions as documented in Documentation/devicetree/bindings/graph.txt. +- port at 0: The input port in the ports node should be connected to a DPI output + port. +- port at 1: The output port in the ports node should be connected to the input + port of a connector node that contains a ddc-i2c-bus property, or to the + input port of an attached bridge chip, such as a SlimPort transmitter. + +HDMI CEC + + +The HDMI CEC controller handles hotplug detection and CEC communication. + +Required properties: +- compatible: Should be "mediatek,-cec" +- reg: Physical base address and length of the controller's registers +- interrupts: The interrupt signal from the function block. +- clocks: device clock + +HDMI DDC + + +The HDMI DDC i2c controller is used to interface with the HDMI DDC pins. +The Mediatek's I2C controller is used to interface with I2C devices. + +Required properties: +- compatible: Should be "mediatek,-hdmi-ddc" +- reg: Physical base address and length of the controller's registers +- clocks: device clock +- clock-names: Should be "ddc-i2c". + +HDMI PHY + + +The HDMI PHY serializes the HDMI encoder's three channel 10-bit parallel +output and drives the HDMI pads. + +Required properties: +- compatible: "mediatek,-hdmi-phy" +- reg: Physical base address and length of the module's registers +- clocks: PLL reference clock +- clock-names: must contain "pll_ref" +- clock-output-names: must be "hdmitx_dig_cts" on mt8173 +- #phy-cells: must be <0> +- #clock-cells: must be <0> + +Optional properties: +- mediatek,ibias: TX DRV bias current for <1.65Gbps, defaults to 0xa +- mediatek,ibias_up: TX DRV bias current for >1.65Gbps, defaults to 0x1c + +Example: + +cec: cec at 10013000 { + compatible = "mediatek,mt8173-cec"; + reg = <0 0x10013000 0 0xbc>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_CEC>; +}; + +hdmi_phy: hdmi-phy at 10209100 { + compatible = "mediatek,mt8173-hdmi-phy"; + reg = <0 0x10209100 0 0x24>; + clocks = <&apmixedsys CLK_APMIXED_HDMI_REF>; + clock-names = "pll_ref"; + clock-output-names = "hdmitx_dig_cts"; + mediatek,ibias = <0xa>; + mediatek,ibias_up = <0x1c>; + #clock-cells = <0>; + #phy-cells = <0>; +}; + +hdmi_ddc0: i2c at 11012000 { + compatible = "mediatek,mt8173-hdmi-ddc"; + reg = <0 0x11012000 0 0x1c>; + interrupts = ; + clocks = <&pericfg CLK_PERI_I2C5>; + clock-names = "ddc-i2c"; +}; + +hdmi0: hdmi at 14025000 { + compatible = "mediatek,mt8173-hdmi"; + reg = <0 0x14025000 0 0x400>; + interrupts = ; + clocks = <&mmsys CLK_MM_HDMI_PIXEL>, +<&mmsys CLK_MM_HDMI_PLLCK>, +<&mmsys CLK_MM_HDMI_AUDIO>, +<&mmsys CLK_MM_HDMI_SPDIF>; + clock-names = "pixel", "pll", "bclk", "spdif"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_pin>; + phys = <&hdmi_phy>; + phy-names = "hdmi"; + mediatek,syscon-hdmi = <&mmsys 0x900>; + assigned-clocks = <&topckgen CLK_TOP_HDMI_SEL>; + assigned-clock-parents = <&hdmi_phy>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port at 0 { + reg = <0>; + + hdmi0_in: endpoint { + remote-endpoint = <&dpi0_out>; +
[PATCH v12 04/14] drm/mediatek: Add DPI sub driver
From: Jie Qiu Add DPI connector/encoder to support HDMI output via the attached HDMI bridge. Signed-off-by: Jie Qiu Signed-off-by: Philipp Zabel --- drivers/gpu/drm/mediatek/Makefile | 3 +- drivers/gpu/drm/mediatek/mtk_dpi.c | 757 drivers/gpu/drm/mediatek/mtk_dpi.h | 85 drivers/gpu/drm/mediatek/mtk_dpi_regs.h | 228 ++ drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 + drivers/gpu/drm/mediatek/mtk_drm_drv.h | 1 + 6 files changed, 1074 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/mediatek/mtk_dpi.c create mode 100644 drivers/gpu/drm/mediatek/mtk_dpi.h create mode 100644 drivers/gpu/drm/mediatek/mtk_dpi_regs.h diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index e781db5a..5fcf58e 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -8,6 +8,7 @@ mediatek-drm-y := mtk_disp_ovl.o \ mtk_drm_gem.o \ mtk_drm_plane.o \ mtk_dsi.o \ - mtk_mipi_tx.o + mtk_mipi_tx.o \ + mtk_dpi.o obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c new file mode 100644 index 000..ae81906 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -0,0 +1,757 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Jie Qiu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtk_dpi.h" +#include "mtk_dpi_regs.h" + +enum mtk_dpi_polarity { + MTK_DPI_POLARITY_RISING, + MTK_DPI_POLARITY_FALLING, +}; + +enum mtk_dpi_power_ctl { + DPI_POWER_START = BIT(0), + DPI_POWER_ENABLE = BIT(1), + DPI_POWER_RESUME = BIT(2), +}; + +struct mtk_dpi_polarities { + enum mtk_dpi_polarity de_pol; + enum mtk_dpi_polarity ck_pol; + enum mtk_dpi_polarity hsync_pol; + enum mtk_dpi_polarity vsync_pol; +}; + +struct mtk_dpi_sync_param { + u32 sync_width; + u32 front_porch; + u32 back_porch; + bool shift_half_line; +}; + +struct mtk_dpi_yc_limit { + u16 y_top; + u16 y_bottom; + u16 c_top; + u16 c_bottom; +}; + +static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) +{ + u32 tmp = readl(dpi->regs + offset) & ~mask; + + tmp |= (val & mask); + writel(tmp, dpi->regs + offset); +} + +static void mtk_dpi_sw_reset(struct mtk_dpi *dpi, bool reset) +{ + mtk_dpi_mask(dpi, DPI_RET, reset ? RST : 0, RST); +} + +static void mtk_dpi_enable(struct mtk_dpi *dpi) +{ + mtk_dpi_mask(dpi, DPI_EN, EN, EN); +} + +static void mtk_dpi_disable(struct mtk_dpi *dpi) +{ + mtk_dpi_mask(dpi, DPI_EN, 0, EN); +} + +static void mtk_dpi_config_hsync(struct mtk_dpi *dpi, +struct mtk_dpi_sync_param *sync) +{ + mtk_dpi_mask(dpi, DPI_TGEN_HWIDTH, +sync->sync_width << HPW, HPW_MASK); + mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, +sync->back_porch << HBP, HBP_MASK); + mtk_dpi_mask(dpi, DPI_TGEN_HPORCH, sync->front_porch << HFP, +HFP_MASK); +} + +static void mtk_dpi_config_vsync(struct mtk_dpi *dpi, +struct mtk_dpi_sync_param *sync, +u32 width_addr, u32 porch_addr) +{ + mtk_dpi_mask(dpi, width_addr, +sync->sync_width << VSYNC_WIDTH_SHIFT, +VSYNC_WIDTH_MASK); + mtk_dpi_mask(dpi, width_addr, +sync->shift_half_line << VSYNC_HALF_LINE_SHIFT, +VSYNC_HALF_LINE_MASK); + mtk_dpi_mask(dpi, porch_addr, +sync->back_porch << VSYNC_BACK_PORCH_SHIFT, +VSYNC_BACK_PORCH_MASK); + mtk_dpi_mask(dpi, porch_addr, +sync->front_porch << VSYNC_FRONT_PORCH_SHIFT, +VSYNC_FRONT_PORCH_MASK); +} + +static void mtk_dpi_config_vsync_lodd(struct mtk_dpi *dpi, + struct mtk_dpi_sync_param *sync) +{ + mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH, DPI_TGEN_VPORCH); +} + +static void mtk_dpi_config_vsync_leven(struct mtk_dpi *dpi, + struct mtk_dpi_sync_param *sync) +{ + mtk_dpi_config_vsync(dpi, sync, DPI_TGEN_VWIDTH_LEVEN, +DPI_TGEN_VPORCH_LEVEN); +} + +static void
[PATCH v12 10/14] clk: mediatek: make dpi0_sel propagate rate changes
This mux is supposed to select a fitting divider after the PLL is already set to the correct rate. Signed-off-by: Philipp Zabel Acked-by: James Liao --- Changes since v10: - Add comments about MUX_GATE rate change propagation --- drivers/clk/mediatek/clk-mt8173.c | 6 +- drivers/clk/mediatek/clk-mtk.h| 15 +-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 227e356..85c0bfc 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -558,7 +558,11 @@ static const struct mtk_composite top_muxes[] __initconst = { MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23), MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31), /* CLK_CFG_6 */ - MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7), + /* +* The dpi0_sel clock should not propagate rate changes to its parent +* clock so the dpi driver can have full control over PLL and divider. +*/ + MUX_GATE_FLAGS(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7, 0), MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15), MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23), MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31), diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h index 32d2e45..9f24fcf 100644 --- a/drivers/clk/mediatek/clk-mtk.h +++ b/drivers/clk/mediatek/clk-mtk.h @@ -83,7 +83,11 @@ struct mtk_composite { signed char num_parents; }; -#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) { \ +/* + * In case the rate change propagation to parent clocks is undesirable, + * this macro allows to specify the clock flags manually. + */ +#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) {\ .id = _id, \ .name = _name, \ .mux_reg = _reg,\ @@ -94,9 +98,16 @@ struct mtk_composite { .divider_shift = -1,\ .parent_names = _parents, \ .num_parents = ARRAY_SIZE(_parents),\ - .flags = CLK_SET_RATE_PARENT, \ + .flags = _flags,\ } +/* + * Unless necessary, all MUX_GATE clocks propagate rate changes to their + * parent clock by default. + */ +#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate)\ + MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, _gate, CLK_SET_RATE_PARENT) + #define MUX(_id, _name, _parents, _reg, _shift, _width) { \ .id = _id, \ .name = _name, \ -- 2.7.0
[PATCH v12 14/14] arm64: dts: mt8173-evb: enable HDMI output
Add an HDMI connector node and enable the devices that are part of the HDMI display path: cec, dpi0, hdmi_phy, and hdmi0. Signed-off-by: Philipp Zabel --- arch/arm64/boot/dts/mediatek/mt8173-evb.dts | 38 + 1 file changed, 38 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts index e427f04..5ee7f24 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-evb.dts +++ b/arch/arm64/boot/dts/mediatek/mt8173-evb.dts @@ -42,6 +42,44 @@ gpio = <&pio 130 GPIO_ACTIVE_HIGH>; enable-active-high; }; + + connector { + compatible = "hdmi-connector"; + label = "hdmi"; + type = "d"; + + port { + hdmi_connector_in: endpoint { + remote-endpoint = <&hdmi0_out>; + }; + }; + }; +}; + +&cec { + status = "okay"; +}; + +&dpi0 { + status = "okay"; +}; + +&hdmi_phy { + status = "okay"; +}; + +&hdmi0 { + status = "okay"; + + ports { + port at 1 { + reg = <1>; + + hdmi0_out: endpoint { + remote-endpoint = <&hdmi_connector_in>; + }; + }; + }; }; &i2c1 { -- 2.7.0
[PATCH v12 12/14] dt-bindings: hdmi-connector: add DDC I2C bus phandle documentation
Add an optional ddc-i2c-bus phandle property that points to an I2C master controller that handles the connector DDC pins. Signed-off-by: Philipp Zabel Acked-by: Rob Herring --- Documentation/devicetree/bindings/display/connector/hdmi-connector.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/connector/hdmi-connector.txt b/Documentation/devicetree/bindings/display/connector/hdmi-connector.txt index acd5668..508aee4 100644 --- a/Documentation/devicetree/bindings/display/connector/hdmi-connector.txt +++ b/Documentation/devicetree/bindings/display/connector/hdmi-connector.txt @@ -8,6 +8,7 @@ Required properties: Optional properties: - label: a symbolic name for the connector - hpd-gpios: HPD GPIO number +- ddc-i2c-bus: phandle link to the I2C controller used for DDC EDID probing Required nodes: - Video port for HDMI input -- 2.7.0
[PATCH v12 07/14] drm/mediatek: enable hdmi output control bit
From: Jie Qiu MT8173 HDMI hardware has a output control bit to enable/disable HDMI output. Because of security reason, so this bit can ONLY be controlled in ARM supervisor mode. Now the only way to enter ARM supervisor is the ARM trusted firmware. So atf provides a API for HDMI driver to call to setup this HDMI control bit to enable HDMI output in supervisor mode. Signed-off-by: Jie Qiu Signed-off-by: Philipp Zabel --- drivers/gpu/drm/mediatek/mtk_hdmi_hw.c | 12 drivers/gpu/drm/mediatek/mtk_hdmi_regs.h | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_hw.c b/drivers/gpu/drm/mediatek/mtk_hdmi_hw.c index 99c7ffc..ea4e35f 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_hw.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_hw.c @@ -15,6 +15,7 @@ #include "mtk_hdmi_regs.h" #include "mtk_hdmi.h" +#include #include #include #include @@ -50,6 +51,17 @@ void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) { + struct arm_smccc_res res; + + /* +* MT8173 HDMI hardware has an output control bit to enable/disable HDMI +* output. This bit can only be controlled in ARM supervisor mode. +* The ARM trusted firmware provides an API for the HDMI driver to set +* this control bit to enable HDMI output in supervisor mode. +*/ + arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, 0x8000, + 0, 0, 0, 0, 0, &res); + regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20, HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0); regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C, diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h b/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h index 8c1d318..d88279f 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h @@ -218,4 +218,5 @@ #define MHL_SYNC_AUTO_EN BIT(30) #define HDMI_PCLK_FREE_RUN BIT(31) +#define MTK_SIP_SET_AUTHORIZED_SECURE_REG 0x8201 #endif -- 2.7.0
[PATCH v12 02/14] drm/mediatek: Add DRM Driver for Mediatek SoC MT8173.
From: CK Hu This patch adds an initial DRM driver for the Mediatek MT8173 DISP subsystem. It currently supports two fixed output streams from the OVL0/OVL1 sources to the DSI0/DPI0 sinks, respectively. Signed-off-by: CK Hu Signed-off-by: YT Shen Signed-off-by: Daniel Kurtz Signed-off-by: Bibby Hsieh Signed-off-by: Mao Huang Signed-off-by: Philipp Zabel --- Changes since v11: - Instead of disabling all planes initally, configure them according to their state. This way the plane doesn't stay disabled until the first flip (which may never happen). - Disable the pipe instead of crashing if any of its components are disabled or missing in the device tree. - Correct parameter type in the mtk_drm_gem_create() declaration --- drivers/gpu/drm/Kconfig | 2 + drivers/gpu/drm/Makefile| 1 + drivers/gpu/drm/mediatek/Kconfig| 12 + drivers/gpu/drm/mediatek/Makefile | 11 + drivers/gpu/drm/mediatek/mtk_disp_ovl.c | 302 +++ drivers/gpu/drm/mediatek/mtk_disp_rdma.c| 240 drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 582 drivers/gpu/drm/mediatek/mtk_drm_crtc.h | 32 ++ drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 355 + drivers/gpu/drm/mediatek/mtk_drm_ddp.h | 41 ++ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 225 +++ drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h | 150 +++ drivers/gpu/drm/mediatek/mtk_drm_drv.c | 579 +++ drivers/gpu/drm/mediatek/mtk_drm_drv.h | 53 +++ drivers/gpu/drm/mediatek/mtk_drm_fb.c | 165 drivers/gpu/drm/mediatek/mtk_drm_fb.h | 23 ++ drivers/gpu/drm/mediatek/mtk_drm_gem.c | 266 + drivers/gpu/drm/mediatek/mtk_drm_gem.h | 59 +++ drivers/gpu/drm/mediatek/mtk_drm_plane.c| 240 drivers/gpu/drm/mediatek/mtk_drm_plane.h| 59 +++ 20 files changed, 3397 insertions(+) create mode 100644 drivers/gpu/drm/mediatek/Kconfig create mode 100644 drivers/gpu/drm/mediatek/Makefile create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_ovl.c create mode 100644 drivers/gpu/drm/mediatek/mtk_disp_rdma.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_crtc.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_crtc.h create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_ddp.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_ddp.h create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.h create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_drv.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_drv.h create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fb.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fb.h create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_gem.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_gem.h create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_plane.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_plane.h diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 8ae7ab6..f7b0d79 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -269,3 +269,5 @@ source "drivers/gpu/drm/imx/Kconfig" source "drivers/gpu/drm/vc4/Kconfig" source "drivers/gpu/drm/etnaviv/Kconfig" + +source "drivers/gpu/drm/mediatek/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 61766de..7b0d1ab 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_DRM_MSM) += msm/ obj-$(CONFIG_DRM_TEGRA) += tegra/ obj-$(CONFIG_DRM_STI) += sti/ obj-$(CONFIG_DRM_IMX) += imx/ +obj-$(CONFIG_DRM_MEDIATEK) += mediatek/ obj-y += i2c/ obj-y += panel/ obj-y += bridge/ diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig new file mode 100644 index 000..8dad892 --- /dev/null +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -0,0 +1,12 @@ +config DRM_MEDIATEK + tristate "DRM Support for Mediatek SoCs" + depends on DRM + depends on ARCH_MEDIATEK || (ARM && COMPILE_TEST) + select DRM_KMS_HELPER + select IOMMU_DMA + select MTK_SMI + help + Choose this option if you have a Mediatek SoCs. + The module will be called mediatek-drm + This driver provides kernel mode setting and + buffer management to userspace. diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile new file mode 100644 index 000..d4bde7c --- /dev/null +++ b/drivers/gpu/drm/mediatek/Makefile @@ -0,0 +1,11 @@ +mediatek-drm-y := mtk_disp_ovl.o \ + mtk_disp_rdma.o \ + mtk_drm_crtc.o \ + mtk_drm_ddp.o \ + mtk_drm_ddp_comp.o \ + mtk_drm_drv.o \ + mtk_drm_fb.o \ + mtk_drm_gem.o \ + mtk_drm_plane.o
[PATCH v12 03/14] drm/mediatek: Add DSI sub driver
From: CK Hu This patch add a drm encoder/connector driver for the MIPI DSI function block of the Mediatek display subsystem and a phy driver for the MIPI TX D-PHY control module. Signed-off-by: Jitao Shi Signed-off-by: Philipp Zabel -- Changes since v10: - add mipi dsi host to pass the dsi lane number, video format, and mode_flag to dsi. --- drivers/gpu/drm/mediatek/Kconfig | 2 + drivers/gpu/drm/mediatek/Makefile | 4 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 2 + drivers/gpu/drm/mediatek/mtk_drm_drv.h | 2 + drivers/gpu/drm/mediatek/mtk_dsi.c | 942 + drivers/gpu/drm/mediatek/mtk_mipi_tx.c | 487 + 6 files changed, 1438 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/mediatek/mtk_dsi.c create mode 100644 drivers/gpu/drm/mediatek/mtk_mipi_tx.c diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index 8dad892..0c49a94 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -3,6 +3,8 @@ config DRM_MEDIATEK depends on DRM depends on ARCH_MEDIATEK || (ARM && COMPILE_TEST) select DRM_KMS_HELPER + select DRM_MIPI_DSI + select DRM_PANEL select IOMMU_DMA select MTK_SMI help diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index d4bde7c..e781db5a 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -6,6 +6,8 @@ mediatek-drm-y := mtk_disp_ovl.o \ mtk_drm_drv.o \ mtk_drm_fb.o \ mtk_drm_gem.o \ - mtk_drm_plane.o + mtk_drm_plane.o \ + mtk_dsi.o \ + mtk_mipi_tx.o obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index fcabfad..4c77c00 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -538,6 +538,8 @@ static struct platform_driver * const mtk_drm_drivers[] = { &mtk_drm_platform_driver, &mtk_disp_ovl_driver, &mtk_disp_rdma_driver, + &mtk_dsi_driver, + &mtk_mipi_tx_driver, }; static int __init mtk_drm_init(void) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index 7a5cb17..2cd04e0 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -49,5 +49,7 @@ struct mtk_drm_private { extern struct platform_driver mtk_disp_ovl_driver; extern struct platform_driver mtk_disp_rdma_driver; +extern struct platform_driver mtk_dsi_driver; +extern struct platform_driver mtk_mipi_tx_driver; #endif /* MTK_DRM_DRV_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c new file mode 100644 index 000..463d389 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -0,0 +1,942 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mtk_drm_ddp_comp.h" + +#define DSI_VIDEO_FIFO_DEPTH (1920 / 4) +#define DSI_HOST_FIFO_DEPTH64 + +#define DSI_START 0x00 + +#define DSI_CON_CTRL 0x10 +#define DSI_RESET BIT(0) +#define DSI_EN BIT(1) + +#define DSI_MODE_CTRL 0x14 +#define MODE (3) +#define CMD_MODE 0 +#define SYNC_PULSE_MODE1 +#define SYNC_EVENT_MODE2 +#define BURST_MODE 3 +#define FRM_MODE BIT(16) +#define MIX_MODE BIT(17) + +#define DSI_TXRX_CTRL 0x18 +#define VC_NUM (2 << 0) +#define LANE_NUM (0xf << 2) +#define DIS_EOTBIT(6) +#define NULL_ENBIT(7) +#define TE_FREERUN BIT(8) +#define EXT_TE_EN BIT(9) +#define EXT_TE_EDGEBIT(10) +#define MAX_RTN_SIZE (0xf << 12) +#define HSTX_CKLP_EN BIT(16) + +#define DSI_PSCTRL 0x1c +#define DSI_PS_WC 0x3fff +#define DSI_PS_SEL (3 << 16) +#define PACKED_PS_16BIT_RGB565 (0 << 16) +#define LOOSELY_PS_18B
[PATCH v12 06/14] drm/mediatek: Add HDMI support
From: Jie Qiu This patch adds drivers for the HDMI bridge connected to the DPI0 display subsystem function block, for the HDMI DDC block, and for the HDMI PHY to support HDMI output. Signed-off-by: Jie Qiu Signed-off-by: Philipp Zabel --- drivers/gpu/drm/mediatek/Kconfig | 7 + drivers/gpu/drm/mediatek/Makefile | 9 + drivers/gpu/drm/mediatek/mtk_cec.c | 245 ++ drivers/gpu/drm/mediatek/mtk_cec.h | 25 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 + drivers/gpu/drm/mediatek/mtk_drm_hdmi_drv.c| 579 ++ drivers/gpu/drm/mediatek/mtk_hdmi.c| 479 ++ drivers/gpu/drm/mediatek/mtk_hdmi.h| 221 + drivers/gpu/drm/mediatek/mtk_hdmi_ddc_drv.c| 362 ++ drivers/gpu/drm/mediatek/mtk_hdmi_hw.c | 652 + drivers/gpu/drm/mediatek/mtk_hdmi_hw.h | 73 +++ drivers/gpu/drm/mediatek/mtk_hdmi_regs.h | 221 + drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c | 505 +++ 13 files changed, 3379 insertions(+) create mode 100644 drivers/gpu/drm/mediatek/mtk_cec.c create mode 100644 drivers/gpu/drm/mediatek/mtk_cec.h create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_hdmi_drv.c create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi.c create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi.h create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_ddc_drv.c create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_hw.c create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_hw.h create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_regs.h create mode 100644 drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig index 0c49a94..e2ff158 100644 --- a/drivers/gpu/drm/mediatek/Kconfig +++ b/drivers/gpu/drm/mediatek/Kconfig @@ -12,3 +12,10 @@ config DRM_MEDIATEK The module will be called mediatek-drm This driver provides kernel mode setting and buffer management to userspace. + +config DRM_MEDIATEK_HDMI + tristate "DRM HDMI Support for Mediatek SoCs" + depends on DRM_MEDIATEK + select GENERIC_PHY + help + DRM/KMS HDMI driver for Mediatek SoCs diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index 5fcf58e..6d53bee 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -12,3 +12,12 @@ mediatek-drm-y := mtk_disp_ovl.o \ mtk_dpi.o obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o + +mediatek-drm-hdmi-objs := mtk_cec.o \ + mtk_drm_hdmi_drv.o \ + mtk_hdmi.o \ + mtk_hdmi_ddc_drv.o \ + mtk_hdmi_hw.o \ + mtk_mt8173_hdmi_phy.o + +obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o diff --git a/drivers/gpu/drm/mediatek/mtk_cec.c b/drivers/gpu/drm/mediatek/mtk_cec.c new file mode 100644 index 000..cba3647 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_cec.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Jie Qiu + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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 +#include +#include +#include +#include + +#include "mtk_cec.h" + +#define TR_CONFIG 0x00 +#define CLEAR_CEC_IRQ BIT(15) + +#define CEC_CKGEN 0x04 +#define CEC_32K_PDNBIT(19) +#define PDNBIT(16) + +#define RX_EVENT 0x54 +#define HDMI_PORD BIT(25) +#define HDMI_HTPLG BIT(24) +#define HDMI_PORD_INT_EN BIT(9) +#define HDMI_HTPLG_INT_EN BIT(8) + +#define RX_GEN_WD 0x58 +#define HDMI_PORD_INT_32K_STATUS BIT(26) +#define RX_RISC_INT_32K_STATUS BIT(25) +#define HDMI_HTPLG_INT_32K_STATUS BIT(24) +#define HDMI_PORD_INT_32K_CLR BIT(18) +#define RX_INT_32K_CLR BIT(17) +#define HDMI_HTPLG_INT_32K_CLR BIT(16) +#define HDMI_PORD_INT_32K_STA_MASK BIT(10) +#define RX_RISC_INT_32K_STA_MASK BIT(9) +#define HDMI_HTPLG_INT_32K_STA_MASKBIT(8) +#define HDMI_PORD_INT_32K_EN BIT(2) +#define RX_INT_32K_EN BIT(1) +#define HDMI_HTPLG_INT_32K_EN BIT(0) + +#define NORMAL_INT_CTRL0x5C +#define HDMI_HTPLG_INT_STA BIT(0) +#define HDMI_PORD_INT_STA BIT(1) +#define HDMI_HTPLG_INT_CLR BIT(16) +#de
[PATCH v12 08/14] arm64: dts: mt8173: Add display subsystem related nodes
From: CK Hu This patch adds the device nodes for the DISP function blocks comprising the display subsystem. Signed-off-by: CK Hu Signed-off-by: Cawa Cheng Signed-off-by: Jie Qiu Signed-off-by: Daniel Kurtz Signed-off-by: Philipp Zabel --- Changes since v10: - reordered nodes by address --- arch/arm64/boot/dts/mediatek/mt8173.dtsi | 235 +++ 1 file changed, 235 insertions(+) diff --git a/arch/arm64/boot/dts/mediatek/mt8173.dtsi b/arch/arm64/boot/dts/mediatek/mt8173.dtsi index 8048811..4ff666d 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173.dtsi @@ -26,6 +26,23 @@ #address-cells = <2>; #size-cells = <2>; + aliases { + ovl0 = &ovl0; + ovl1 = &ovl1; + rdma0 = &rdma0; + rdma1 = &rdma1; + rdma2 = &rdma2; + wdma0 = &wdma0; + wdma1 = &wdma1; + color0 = &color0; + color1 = &color1; + split0 = &split0; + split1 = &split1; + dpi0 = &dpi0; + dsi0 = &dsi0; + dsi1 = &dsi1; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -295,6 +312,26 @@ #clock-cells = <1>; }; + mipi_tx0: mipi-dphy at 10215000 { + compatible = "mediatek,mt8173-mipi-tx"; + reg = <0 0x10215000 0 0x1000>; + clocks = <&clk26m>; + clock-output-names = "mipi_tx0_pll"; + #clock-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + + mipi_tx1: mipi-dphy at 10216000 { + compatible = "mediatek,mt8173-mipi-tx"; + reg = <0 0x10216000 0 0x1000>; + clocks = <&clk26m>; + clock-output-names = "mipi_tx1_pll"; + #clock-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + gic: interrupt-controller at 1022 { compatible = "arm,gic-400"; #interrupt-cells = <3>; @@ -441,6 +478,14 @@ status = "disabled"; }; + hdmiddc0: i2c at 11012000 { + compatible = "mediatek,mt8173-hdmi-ddc"; + interrupts = ; + reg = <0 0x11012000 0 0x1C>; + clocks = <&pericfg CLK_PERI_I2C5>; + clock-names = "ddc-i2c"; + }; + i2c6: i2c at 11013000 { compatible = "mediatek,mt8173-i2c"; reg = <0 0x11013000 0 0x70>, @@ -576,7 +621,183 @@ mmsys: clock-controller at 1400 { compatible = "mediatek,mt8173-mmsys", "syscon"; reg = <0 0x1400 0 0x1000>; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; #clock-cells = <1>; + + /* FIXME - remove iommus here */ + iommus = <&iommu M4U_PORT_DISP_OVL0>, +<&iommu M4U_PORT_DISP_OVL1>; + }; + + ovl0: ovl at 1400c000 { + compatible = "mediatek,mt8173-disp-ovl"; + reg = <0 0x1400c000 0 0x1000>; + interrupts = ; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + clocks = <&mmsys CLK_MM_DISP_OVL0>; + iommus = <&iommu M4U_PORT_DISP_OVL0>; + mediatek,larb = <&larb0>; + }; + + ovl1: ovl at 1400d000 { + compatible = "mediatek,mt8173-disp-ovl"; + reg = <0 0x1400d000 0 0x1000>; + interrupts = ; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + clocks = <&mmsys CLK_MM_DISP_OVL1>; + iommus = <&iommu M4U_PORT_DISP_OVL1>; + mediatek,larb = <&larb4>; + }; + + rdma0: rdma at 1400e000 { + compatible = "mediatek,mt8173-disp-rdma"; + reg = <0 0x1400e000 0 0x1000>; + interrupts = ; + power-domains = <&scpsys MT8173_POWER_DOMAIN_MM>; + clocks = <&mmsys CLK_MM_DISP_RDMA0>; + iommus = <&iommu M4U_PORT_DISP_RDMA0>; + mediatek,larb = <&larb0>; + }; + + rdma1: rdma at 1400f000 { + compatible = "mediatek,mt8173-disp-rdma"; +
[PATCH v12 13/14] clk: mediatek: remove hdmitx_dig_cts from TOP clocks
The hdmitx_dig_cts clock signal is not a child of tvdpll_445p5m, but is routed out of the HDMI PHY module. Signed-off-by: Philipp Zabel Acked-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt8173.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index cf4fcb6..10c9860 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -61,7 +61,6 @@ static const struct mtk_fixed_factor top_divs[] __initconst = { FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793), FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1), - FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "tvdpll_445p5m", 1, 3), FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2), FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3), -- 2.7.0
[PATCH v12 11/14] clk: mediatek: Add hdmi_ref HDMI PHY PLL reference clock output
The configurable hdmi_ref output of the PLL block is derived from the tvdpll_594m clock signal via a configurable PLL post-divider. It is used as the PLL reference input to the HDMI PHY module. Signed-off-by: Philipp Zabel Acked-by: James Liao Acked-by: Stephen Boyd --- drivers/clk/mediatek/clk-mt8173.c | 5 + include/dt-bindings/clock/mt8173-clk.h | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c index 85c0bfc..cf4fcb6 100644 --- a/drivers/clk/mediatek/clk-mt8173.c +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -1095,6 +1095,11 @@ static void __init mtk_apmixedsys_init(struct device_node *node) clk_data->clks[cku->id] = clk; } + clk = clk_register_divider(NULL, "hdmi_ref", "tvdpll_594m", 0, + base + 0x40, 16, 3, CLK_DIVIDER_POWER_OF_TWO, + NULL); + clk_data->clks[CLK_APMIXED_HDMI_REF] = clk; + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); if (r) pr_err("%s(): could not register clock provider: %d\n", diff --git a/include/dt-bindings/clock/mt8173-clk.h b/include/dt-bindings/clock/mt8173-clk.h index 7956ba1..6094bf7 100644 --- a/include/dt-bindings/clock/mt8173-clk.h +++ b/include/dt-bindings/clock/mt8173-clk.h @@ -176,7 +176,8 @@ #define CLK_APMIXED_LVDSPLL13 #define CLK_APMIXED_MSDCPLL2 14 #define CLK_APMIXED_REF2USB_TX 15 -#define CLK_APMIXED_NR_CLK 16 +#define CLK_APMIXED_HDMI_REF 16 +#define CLK_APMIXED_NR_CLK 17 /* INFRA_SYS */ -- 2.7.0
[Bug 94249] Topaz GPU not working correctly
https://bugs.freedesktop.org/show_bug.cgi?id=94249 --- Comment #2 from Armin K --- I'm sorry I didn't reply earlier, I didn't get the mail that there was a reply. Using runpm=0 didn't change a thing. I forgot to post the corrupted lspci data as said in the original post: 01:00.0 Display controller [0380]: Advanced Micro Devices, Inc. [AMD/ATI] Topaz XT [Radeon R7 M260/M265] [1002:6900] (rev ff) (prog-if ff) !!! Unknown header type 7f Kernel driver in use: amdgpu Kernel modules: amdgpu Without the amdgpu module loaded, it looks as down below (with other options included with -v). The X server still crashes when AMDGPU DDX is present. Here's the relevant part of the Xorg.log: Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) Backtrace: Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 0: /usr/libexec/Xorg (OsInit+0x35a) [0x5ca1aa] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 1: /lib/libc.so.6 (killpg+0x40) [0x7f5cfaf453df] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 2: /usr/lib/libdrm_amdgpu.so.1 (amdgpu_cs_submit+0x333) [0x7f5cf56ff383] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 3: /usr/lib/libdrm_amdgpu.so.1 (amdgpu_cs_submit+0x3b) [0x7f5cf56ff02b] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 4: /usr/lib/dri/radeonsi_dri.so (radeon_drm_winsys_create+0x14fad) [0x7f5cf451e3ed] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 5: /usr/lib/dri/radeonsi_dri.so (__driDriverGetExtensions_radeonsi+0x45afe1) [0x7f5cf48ecce1] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 6: /usr/lib/dri/radeonsi_dri.so (amdgpu_winsys_create+0x18f9) [0x7f5cf450dc59] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 7: /usr/lib/dri/radeonsi_dri.so (amdgpu_winsys_create+0x5a60) [0x7f5cf4515d80] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 8: /usr/lib/dri/radeonsi_dri.so (__driDriverGetExtensions_radeonsi+0x45b6ce) [0x7f5cf48eda8e] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 9: /usr/lib/dri/radeonsi_dri.so (__driDriverGetExtensions_radeonsi+0x45b448) [0x7f5cf48ed6d8] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 10: /usr/lib/dri/radeonsi_dri.so (amdgpu_winsys_create+0xba8) [0x7f5cf450b688] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) unw_get_proc_name failed: no unwind info found [-10] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 11: /usr/lib/dri/radeonsi_dri.so (?+0xba8) [0x7f5cf4037938] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 12: /usr/lib/dri/radeonsi_dri.so (__driDriverGetExtensions_radeonsi+0x2f81cf) [0x7f5cf462722f] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 13: /usr/lib/dri/radeonsi_dri.so (__driDriverGetExtensions_radeonsi+0x2f5269) [0x7f5cf4621269] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 14: /usr/lib/libgbm.so.1 (gbm_surface_has_free_buffers+0xcfb) [0x7f5cf54f38cb] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 15: /usr/lib/libgbm.so.1 (gbm_surface_has_free_buffers+0xe8) [0x7f5cf54f2108] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 16: /usr/lib/libgbm.so.1 (gbm_create_device+0xa4) [0x7f5cf54f1dc4] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 17: /usr/lib/xorg/modules/drivers/amdgpu_drv.so (_init+0x828b) [0x7f5cf5919d6b] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 18: /usr/libexec/Xorg (InitOutput+0xb52) [0x480732] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 19: /usr/libexec/Xorg (remove_fs_handlers+0x498) [0x4396d8] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 20: /lib/libc.so.6 (__libc_start_main+0xf0) [0x7f5cfaf307a0] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 21: /usr/libexec/Xorg (_start+0x29) [0x421529] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) 22: ? (?+0x29) [0x29] Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) Segmentation fault at address 0x10 Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: Fatal server error: Mar 01 16:23:34 krejzi /usr/libexec/gdm-x-session[629]: (EE) Caught signal 11 (Segmentation fault). Server aborting Ignore the /usr/libexec/gdm-x-session, as GNOME's gdm reditects Xorg.log to systemd journal instead. -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160301/78c986a2/attachment-0001.html>
Alternative binding proposal for tda998x audio (Was: Re: [PATCH RFC v5 4/8] drm/i2c: tda998x: Add support of a DT graph of ports)
On Tue, 1 Mar 2016 16:26:50 +0200 Jyri Sarha wrote: > Ok, here is just one more simple alternative for tda998x audio binding. > I feel that the graph ports binding for audio does not make sense > without a graph based ASoC machine driver implementation. The ASoC > simple-card is already here and it so widely used that there is no > getting rid of that any time soon. This proposal provides the same > functionality as the patch in the root of this thread, but in a simpler > way and is equally compatible with simple-card. Hi Jyri, The graph port binding for the tda998x works fine with the simple card driver when multi-codec support is added. See http://mailman.alsa-project.org/pipermail/alsa-devel/2015-January/085855.html -- Ken ar c'hentañ| ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/
Alternative binding proposal for tda998x audio (Was: Re: [PATCH RFC v5 4/8] drm/i2c: tda998x: Add support of a DT graph of ports)
On 03/01/16 17:35, Jean-Francois Moine wrote: > On Tue, 1 Mar 2016 16:26:50 +0200 > Jyri Sarha wrote: > >> Ok, here is just one more simple alternative for tda998x audio binding. >> I feel that the graph ports binding for audio does not make sense >> without a graph based ASoC machine driver implementation. The ASoC >> simple-card is already here and it so widely used that there is no >> getting rid of that any time soon. This proposal provides the same >> functionality as the patch in the root of this thread, but in a simpler >> way and is equally compatible with simple-card. > > Hi Jyri, > > The graph port binding for the tda998x works fine with the simple card > driver when multi-codec support is added. See > http://mailman.alsa-project.org/pipermail/alsa-devel/2015-January/085855.html > I know that it works, I have used it myself until now, but it is not needed and there is no driver that parses audio port endpoints. I see no point specifying something in the binding that is not used and there no specific plan to ever use it. AFAIU my proposed binding should work equally well with simple-card, with or without multi-codec support. Best regards, Jyri
[GIT PULL] imx-drm vblank IRQ control, fence sync support, and of endpoint helpers
Hi Dave, could you merge these imx-drm updates? This pull request contains the drm_of_active_endpoint helpers to consolidate code between imx-drm and rockchip and a few imx-drm improvements, most notably fence synchronisation support for importing dma-bufs from etnaviv. regards Philipp The following changes since commit 316e376b658f67cd63351a55093ac5038637a330: Merge tag 'topic/drm-misc-2016-02-08' of git://anongit.freedesktop.org/drm-intel into drm-next (2016-02-09 10:39:11 +1000) are available in the git repository at: git://git.pengutronix.de/git/pza/linux.git tags/imx-drm-next-20160301 for you to fetch changes up to 411b0336cf9fc988ff11de3f1e66587fe88fb980: drm/imx: only enable vblank IRQs when needed (2016-03-01 08:33:41 +0100) imx-drm vblank IRQ control, fence support, and of endpoint helpers - Add and make use of drm_of_active_endpoint helpers - Silence a noisy dev_info into a dev_dbg - Stop touching primary fb on pageflips - Track flip state explicitly - Keep GEM buffer objects referenced while scanout is active - Implement fence sync by deferring flips to a workqueue for dma-bufs with pending fences - Actually disable vblank IRQs while they are not needed Liu Ying (1): drm/imx: ipuv3 plane: Replace dev_info with dev_dbg if a plane's CRTC changes Lucas Stach (5): drm/imx: don't touch primary fb on pageflip drm/imx: track flip state explicitly drm/imx: keep GEM object referenced as long as scanout is active drm/imx: implement fence sync drm/imx: only enable vblank IRQs when needed Philipp Zabel (4): drm: add drm_of_encoder_active_endpoint helpers drm/imx: remove imx_drm_encoder_get_mux_id drm/rockchip: remove rockchip_drm_encoder_get_mux_id gpu: ipu-v3: ipu-dc: Simplify display controller microcode setup drivers/gpu/drm/drm_of.c| 34 +++ drivers/gpu/drm/imx/dw_hdmi-imx.c | 2 +- drivers/gpu/drm/imx/imx-drm-core.c | 31 --- drivers/gpu/drm/imx/imx-drm.h | 2 - drivers/gpu/drm/imx/imx-ldb.c | 5 +- drivers/gpu/drm/imx/ipuv3-crtc.c| 133 +--- drivers/gpu/drm/imx/ipuv3-plane.c | 2 +- drivers/gpu/drm/rockchip/dw-mipi-dsi.c | 2 +- drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 30 --- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 2 - drivers/gpu/ipu-v3/ipu-dc.c | 53 ++- include/drm/drm_of.h| 33 +++ 13 files changed, 222 insertions(+), 109 deletions(-)
Alternative binding proposal for tda998x audio (Was: Re: [PATCH RFC v5 4/8] drm/i2c: tda998x: Add support of a DT graph of ports)
On Tue, 1 Mar 2016 17:51:09 +0200 Jyri Sarha wrote: > I know that it works, I have used it myself until now, but it is not > needed and there is no driver that parses audio port endpoints. I see no > point specifying something in the binding that is not used and there no > specific plan to ever use it. > > AFAIU my proposed binding should work equally well with simple-card, > with or without multi-codec support. As told many times, the simple card is a pure Linux specific entity. It does not describe any hardware. It should not appear in a DT, or, if it does, its compatible should be "linux, simple-audio-card". Then, how can the other OSs know the links between the audio devices and the audio encoders/connectors? On the other way, the audio graph does not impose any particular software design. It just describes the links between the different hardware components and each OS is free to implement its own layout. -- Ken ar c'hentañ| ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/
[PATCH v7 3/7] drm,i915: introduce drm_malloc_gfp()
From: Chris Wilson I have instances where I want to use drm_malloc_ab() but with a custom gfp mask. And with those, where I want a temporary allocation, I want to try a high-order kmalloc() before using a vmalloc(). So refactor my usage into drm_malloc_gfp(). Signed-off-by: Chris Wilson Cc: dri-devel at lists.freedesktop.org Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Acked-by: Dave Airlie Signed-off-by: Dave Gordon --- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 +++- drivers/gpu/drm/i915/i915_gem_gtt.c| 5 +++-- drivers/gpu/drm/i915/i915_gem_userptr.c| 15 --- include/drm/drm_mem_util.h | 19 +++ 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 1328bc5..f734b3c 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1775,11 +1775,9 @@ static bool only_mappable_for_reloc(unsigned int flags) return -EINVAL; } - exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count, -GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); - if (exec2_list == NULL) - exec2_list = drm_malloc_ab(sizeof(*exec2_list), - args->buffer_count); + exec2_list = drm_malloc_gfp(sizeof(*exec2_list), + args->buffer_count, + GFP_TEMPORARY); if (exec2_list == NULL) { DRM_DEBUG("Failed to allocate exec list for %d buffers\n", args->buffer_count); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 49e4f26..6af2462 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -3416,8 +3416,9 @@ struct i915_vma * int ret = -ENOMEM; /* Allocate a temporary list of source pages for random access. */ - page_addr_list = drm_malloc_ab(obj->base.size / PAGE_SIZE, - sizeof(dma_addr_t)); + page_addr_list = drm_malloc_gfp(obj->base.size / PAGE_SIZE, + sizeof(dma_addr_t), + GFP_TEMPORARY); if (!page_addr_list) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 4b09c84..4c98c8c 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -494,10 +494,7 @@ struct get_pages_work { ret = -ENOMEM; pinned = 0; - pvec = kmalloc(npages*sizeof(struct page *), - GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); - if (pvec == NULL) - pvec = drm_malloc_ab(npages, sizeof(struct page *)); + pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY); if (pvec != NULL) { struct mm_struct *mm = obj->userptr.mm->mm; @@ -634,14 +631,10 @@ struct get_pages_work { pvec = NULL; pinned = 0; if (obj->userptr.mm->mm == current->mm) { - pvec = kmalloc(num_pages*sizeof(struct page *), - GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY); + pvec = drm_malloc_gfp(num_pages, sizeof(struct page *), GFP_TEMPORARY); if (pvec == NULL) { - pvec = drm_malloc_ab(num_pages, sizeof(struct page *)); - if (pvec == NULL) { - __i915_gem_userptr_set_active(obj, false); - return -ENOMEM; - } + __i915_gem_userptr_set_active(obj, false); + return -ENOMEM; } pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages, diff --git a/include/drm/drm_mem_util.h b/include/drm/drm_mem_util.h index e42495a..741ce75 100644 --- a/include/drm/drm_mem_util.h +++ b/include/drm/drm_mem_util.h @@ -54,6 +54,25 @@ static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size) GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); } +static __inline__ void *drm_malloc_gfp(size_t nmemb, size_t size, gfp_t gfp) +{ + if (size != 0 && nmemb > SIZE_MAX / size) + return NULL; + + if (size * nmemb <= PAGE_SIZE) + return kmalloc(nmemb * size, gfp); + + if (gfp & __GFP_RECLAIMABLE) { + void *ptr = kmalloc(nmemb * size, + gfp | __GFP_NOWARN | __GFP_NORETRY); + if (ptr) + return ptr; + } + + return __vmalloc(size * nmemb, +gfp | __GFP_HIGHMEM, PAGE_KERNEL); +} + static __inline void drm_free_large(void *ptr) { kvfree(ptr); -- 1.9.
[PATCH v7 7/7] drm: add parameter-order checking to drm memory allocators
After the recent addition of drm_malloc_gfp(), it was noticed that some callers of these functions has swapped the parameters in the call - it's supposed to be 'number of members' and 'sizeof(element)', but a few callers had got the size first and the count second. This isn't otherwise detected because they're both type 'size_t', and the implementation at present just multiplies them anyway, so the result is still right. But some future implementation might treat them differently (e.g. allowing 0 elements but not zero size), so let's add some compile-time checks and complain if the second (size) parameter isn't a sizeof() expression, or at least a compile-time constant. This patch also fixes those callers where the order was wrong. v6: removed duplicate BUILD_BUG_ON_MSG(); avoided renaming functions by shadowing them with #defines and then calling the function (non-recursively!) from inside the #define [Chris Wilson] Signed-off-by: Dave Gordon Cc: Chris Wilson Cc: Ville Syrjälä Cc: dri- Cc: dri-devel at lists.freedesktop.org --- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 2 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 include/drm/drm_mem_util.h | 27 --- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 1aba01a..9ae4a71 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -340,7 +340,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, */ bos = drm_malloc_ab(args->nr_bos, sizeof(*bos)); relocs = drm_malloc_ab(args->nr_relocs, sizeof(*relocs)); - stream = drm_malloc_ab(1, args->stream_size); + stream = drm_malloc_ab(args->stream_size, sizeof(*stream)); cmdbuf = etnaviv_gpu_cmdbuf_new(gpu, ALIGN(args->stream_size, 8) + 8, args->nr_bos); if (!bos || !relocs || !stream || !cmdbuf) { diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index f734b3c..1a136d9 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1686,8 +1686,8 @@ static bool only_mappable_for_reloc(unsigned int flags) } /* Copy in the exec list from userland */ - exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count); - exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count); + exec_list = drm_malloc_ab(args->buffer_count, sizeof(*exec_list)); + exec2_list = drm_malloc_ab(args->buffer_count, sizeof(*exec2_list)); if (exec_list == NULL || exec2_list == NULL) { DRM_DEBUG("Failed to allocate exec list for %d buffers\n", args->buffer_count); @@ -1775,8 +1775,8 @@ static bool only_mappable_for_reloc(unsigned int flags) return -EINVAL; } - exec2_list = drm_malloc_gfp(sizeof(*exec2_list), - args->buffer_count, + exec2_list = drm_malloc_gfp(args->buffer_count, + sizeof(*exec2_list), GFP_TEMPORARY); if (exec2_list == NULL) { DRM_DEBUG("Failed to allocate exec list for %d buffers\n", diff --git a/include/drm/drm_mem_util.h b/include/drm/drm_mem_util.h index 741ce75..5b0111c 100644 --- a/include/drm/drm_mem_util.h +++ b/include/drm/drm_mem_util.h @@ -29,7 +29,7 @@ #include -static __inline__ void *drm_calloc_large(size_t nmemb, size_t size) +static __inline__ void *drm_calloc_large(size_t nmemb, const size_t size) { if (size != 0 && nmemb > SIZE_MAX / size) return NULL; @@ -41,8 +41,15 @@ static __inline__ void *drm_calloc_large(size_t nmemb, size_t size) GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); } +#definedrm_calloc_large(nmemb, size) \ +({ \ + BUILD_BUG_ON_MSG(!__builtin_constant_p(size), \ + "Non-constant 'size' - check argument ordering?"); \ + (drm_calloc_large)(nmemb, size);\ +}) + /* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */ -static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size) +static __inline__ void *drm_malloc_ab(size_t nmemb, const size_t size) { if (size != 0 && nmemb > SIZE_MAX / size) return NULL; @@ -54,7 +61,14 @@ static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size) GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL); } -static __inline__ void *drm_malloc_gfp(size_t nmemb, size_t size, gfp_t gfp) +#definedrm_malloc_ab(nmemb, size)
[PATCH] gpu: drm: rcar-du: rcar_du_drv: don't open code of_device_get_match_data()
From: Wolfram Sang This change will also make Coverity happy by avoiding a theoretical NULL pointer dereference; yet another reason is to use the above helper function to tighten the code and make it more readable. Signed-off-by: Wolfram Sang --- Compile tested only. I am on the road and can't test the multimedia drivers because of no cables :( If someone could test it, that would be much appreciated. Or I'll do it next week. The pattern worked for other drivers I could actually test, though. drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index ed6006bf6bd893..ac95509e80bb7c 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -318,7 +318,7 @@ static int rcar_du_probe(struct platform_device *pdev) init_waitqueue_head(&rcdu->commit.wait); rcdu->dev = &pdev->dev; - rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data; + rcdu->info = of_device_get_match_data(rcdu->dev); ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); if (!ddev) -- 2.7.0
[Intel-gfx] [PATCH v2 5/6] drm/atomic: Handle encoder assignment conflicts in a separate check.
On Wed, Feb 24, 2016 at 09:37:32AM +0100, Maarten Lankhorst wrote: > The current check doesn't handle the case where we don't steal an > encoder, but keep it on the current connector. If we repurpose > disable_conflicting_encoders to do the checking, we just have > to reject the ones that conflict. > > Signed-off-by: Maarten Lankhorst > Testcase: kms_setmode.invalid-clone-single-crtc-stealing > --- > drivers/gpu/drm/drm_atomic_helper.c | 58 > +++-- > 1 file changed, 24 insertions(+), 34 deletions(-) > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > b/drivers/gpu/drm/drm_atomic_helper.c > index 3543c7fcd072..32bd5bebef0b 100644 > --- a/drivers/gpu/drm/drm_atomic_helper.c > +++ b/drivers/gpu/drm/drm_atomic_helper.c > @@ -86,7 +86,8 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state > *state, > } > } > > -static int disable_conflicting_connectors(struct drm_atomic_state *state) > +static int handle_conflicting_encoders(struct drm_atomic_state *state, > +bool disable_conflicting_encoders) > { > struct drm_connector_state *conn_state; > struct drm_connector *connector; > @@ -106,8 +107,17 @@ static int disable_conflicting_connectors(struct > drm_atomic_state *state) > else > new_encoder = funcs->best_encoder(connector); > > - if (new_encoder) > + if (new_encoder) { > + if (encoder_mask & (1 << > drm_encoder_index(new_encoder))) { > + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] on > [CONNECTOR:%d:%s] already assigned\n", > + new_encoder->base.id, new_encoder->name, > + connector->base.id, connector->name); > + > + return -EINVAL; > + } > + > encoder_mask |= 1 << drm_encoder_index(new_encoder); > + } > } > > drm_for_each_connector(connector, state->dev) { > @@ -120,6 +130,15 @@ static int disable_conflicting_connectors(struct > drm_atomic_state *state) > if (!encoder || !(encoder_mask & (1 << > drm_encoder_index(encoder > continue; > > + if (!disable_conflicting_encoders) { > + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on > [CRTC:%d:%s] by [CONNECTOR:%d:%s]\n", > + encoder->base.id, encoder->name, > + connector->state->crtc->base.id, > + connector->state->crtc->name, > + connector->base.id, connector->name); > + return -EINVAL; > + } > + Hmm. This can't possibly work can it? If I'm reding things correctly this would already fail if we have crtc0->enc0->conn0 and then try to change it to crtc1->enc0->conn0. But perhaps I'm missing some subtle thing (there are a lot of those in our atomic framework due to thing automagically getting added to the state). The idea I had for checking things was something like: for legacy setcrtc: for_new_connstate() if (!state->crtc) continue; enc = ->best_encoder(); if (encoder_mask & 1 << enc.index) fail; encoder_mask |= 1 << enc.index; for_all_connectors if (new_state) continue; if (!old_state->crtc) continue; enc = conn->best_encoder; if (encoder_mask & 1 << enc.index) disable_connector; for atomic: for_all_connectors if (new_state) state = new_state; else state = old_state; if (!state->crtc) continue; if (new_state) enc = ->best_encoder() else enc = conn->best_encoder; if (encoder_mask & 1 << enc.index) fail; encoder_mask |= 1 << enc.index; Though I'm not entirely sure the legacy variant would work correctly due to something maybe adding the connector to the state even though it's not part of the set that the user requested. I might need to think more on this. > conn_state = drm_atomic_get_connector_state(state, connector); > if (IS_ERR(conn_state)) > return PTR_ERR(conn_state); > @@ -148,26 +167,6 @@ static int disable_conflicting_connectors(struct > drm_atomic_state *state) > return 0; > } > > -static bool > -check_pending_encoder_assignment(struct drm_atomic_state *state, > - struct drm_encoder *new_encoder) > -{ > - struct drm_connector *connector; > - struct drm_connector_state *conn_state; > - int i; > - > - for_each_connector_in_state(state, connector, conn_state, i) { > - if (conn_state->best_encoder != new_encoder) > -
[Bug 94354] R9285 Unigine Valley perf regression since radeonsi: use re-Z
https://bugs.freedesktop.org/show_bug.cgi?id=94354 Bug ID: 94354 Summary: R9285 Unigine Valley perf regression since radeonsi: use re-Z Product: Mesa Version: git Hardware: Other OS: All Status: NEW Severity: normal Priority: medium Component: Drivers/Gallium/radeonsi Assignee: dri-devel at lists.freedesktop.org Reporter: adf.lists at gmail.com QA Contact: dri-devel at lists.freedesktop.org Haven't tested other apps/settings, but on R9285 Unigine Valley on highest settings, 8x AA, 1920x1080 fullscreen is slower after d0f3b524cdb8489a6872ba3639a13813de221fc2 radeonsi: use re-Z This can increase perf for shaders that kill pixels (kill, alpha-test, alpha-to-coverage). Before FPS: 27.2 Score: 1139 Min FPS: 13.5 Max FPS: 52.0 After FPS: 22.6 Score: 946 Min FPS: 11.7 Max FPS: 47.1 -- You are receiving this mail because: You are the assignee for the bug. -- next part -- An HTML attachment was scrubbed... URL: <https://lists.freedesktop.org/archives/dri-devel/attachments/20160301/42afecf0/attachment.html>
[Intel-gfx] [PATCH v2 5/6] drm/atomic: Handle encoder assignment conflicts in a separate check.
Op 01-03-16 om 18:21 schreef Ville Syrjälä: > On Wed, Feb 24, 2016 at 09:37:32AM +0100, Maarten Lankhorst wrote: >> The current check doesn't handle the case where we don't steal an >> encoder, but keep it on the current connector. If we repurpose >> disable_conflicting_encoders to do the checking, we just have >> to reject the ones that conflict. >> >> Signed-off-by: Maarten Lankhorst >> Testcase: kms_setmode.invalid-clone-single-crtc-stealing >> --- >> drivers/gpu/drm/drm_atomic_helper.c | 58 >> +++-- >> 1 file changed, 24 insertions(+), 34 deletions(-) >> >> diff --git a/drivers/gpu/drm/drm_atomic_helper.c >> b/drivers/gpu/drm/drm_atomic_helper.c >> index 3543c7fcd072..32bd5bebef0b 100644 >> --- a/drivers/gpu/drm/drm_atomic_helper.c >> +++ b/drivers/gpu/drm/drm_atomic_helper.c >> @@ -86,7 +86,8 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state >> *state, >> } >> } >> >> -static int disable_conflicting_connectors(struct drm_atomic_state *state) >> +static int handle_conflicting_encoders(struct drm_atomic_state *state, >> + bool disable_conflicting_encoders) >> { >> struct drm_connector_state *conn_state; >> struct drm_connector *connector; >> @@ -106,8 +107,17 @@ static int disable_conflicting_connectors(struct >> drm_atomic_state *state) >> else >> new_encoder = funcs->best_encoder(connector); >> >> -if (new_encoder) >> +if (new_encoder) { >> +if (encoder_mask & (1 << >> drm_encoder_index(new_encoder))) { >> +DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] on >> [CONNECTOR:%d:%s] already assigned\n", >> +new_encoder->base.id, new_encoder->name, >> +connector->base.id, connector->name); >> + >> +return -EINVAL; >> +} >> + >> encoder_mask |= 1 << drm_encoder_index(new_encoder); >> +} >> } >> >> drm_for_each_connector(connector, state->dev) { >> @@ -120,6 +130,15 @@ static int disable_conflicting_connectors(struct >> drm_atomic_state *state) >> if (!encoder || !(encoder_mask & (1 << >> drm_encoder_index(encoder >> continue; >> >> +if (!disable_conflicting_encoders) { >> +DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on >> [CRTC:%d:%s] by [CONNECTOR:%d:%s]\n", >> + encoder->base.id, encoder->name, >> + connector->state->crtc->base.id, >> + connector->state->crtc->name, >> + connector->base.id, connector->name); >> +return -EINVAL; >> +} >> + > Hmm. This can't possibly work can it? If I'm reding things correctly > this would already fail if we have crtc0->enc0->conn0 and then try to > change it to crtc1->enc0->conn0. But perhaps I'm missing some subtle > thing (there are a lot of those in our atomic framework due to thing > automagically getting added to the state). > No, in that case the connector is part of the state. This boils down to: if (stealing encoder from existing connector not part of state) if (atomic) return -EINVAL; else // disable connector and possibly crtc ~Maarten
[Intel-gfx] [PATCH v2 5/6] drm/atomic: Handle encoder assignment conflicts in a separate check.
On Tue, Mar 01, 2016 at 06:45:53PM +0100, Maarten Lankhorst wrote: > Op 01-03-16 om 18:21 schreef Ville Syrjälä: > > On Wed, Feb 24, 2016 at 09:37:32AM +0100, Maarten Lankhorst wrote: > >> The current check doesn't handle the case where we don't steal an > >> encoder, but keep it on the current connector. If we repurpose > >> disable_conflicting_encoders to do the checking, we just have > >> to reject the ones that conflict. > >> > >> Signed-off-by: Maarten Lankhorst > >> Testcase: kms_setmode.invalid-clone-single-crtc-stealing > >> --- > >> drivers/gpu/drm/drm_atomic_helper.c | 58 > >> +++-- > >> 1 file changed, 24 insertions(+), 34 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/drm_atomic_helper.c > >> b/drivers/gpu/drm/drm_atomic_helper.c > >> index 3543c7fcd072..32bd5bebef0b 100644 > >> --- a/drivers/gpu/drm/drm_atomic_helper.c > >> +++ b/drivers/gpu/drm/drm_atomic_helper.c > >> @@ -86,7 +86,8 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state > >> *state, > >>} > >> } > >> > >> -static int disable_conflicting_connectors(struct drm_atomic_state *state) > >> +static int handle_conflicting_encoders(struct drm_atomic_state *state, > >> + bool disable_conflicting_encoders) > >> { > >>struct drm_connector_state *conn_state; > >>struct drm_connector *connector; > >> @@ -106,8 +107,17 @@ static int disable_conflicting_connectors(struct > >> drm_atomic_state *state) > >>else > >>new_encoder = funcs->best_encoder(connector); > >> > >> - if (new_encoder) > >> + if (new_encoder) { > >> + if (encoder_mask & (1 << > >> drm_encoder_index(new_encoder))) { > >> + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] on > >> [CONNECTOR:%d:%s] already assigned\n", > >> + new_encoder->base.id, new_encoder->name, > >> + connector->base.id, connector->name); > >> + > >> + return -EINVAL; > >> + } > >> + > >>encoder_mask |= 1 << drm_encoder_index(new_encoder); > >> + } > >>} > >> > >>drm_for_each_connector(connector, state->dev) { > >> @@ -120,6 +130,15 @@ static int disable_conflicting_connectors(struct > >> drm_atomic_state *state) > >>if (!encoder || !(encoder_mask & (1 << > >> drm_encoder_index(encoder > >>continue; > >> > >> + if (!disable_conflicting_encoders) { > >> + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on > >> [CRTC:%d:%s] by [CONNECTOR:%d:%s]\n", > >> + encoder->base.id, encoder->name, > >> + connector->state->crtc->base.id, > >> + connector->state->crtc->name, > >> + connector->base.id, connector->name); > >> + return -EINVAL; > >> + } > >> + > > Hmm. This can't possibly work can it? If I'm reding things correctly > > this would already fail if we have crtc0->enc0->conn0 and then try to > > change it to crtc1->enc0->conn0. But perhaps I'm missing some subtle > > thing (there are a lot of those in our atomic framework due to thing > > automagically getting added to the state). > > > No, in that case the connector is part of the state. Doh, I misread the condition for the existing state check. OK, so I guess this is more or less what I had in mind as well, except it uses the two loops version for both cases. The one difference between my idea and this is that you don't include the old encoders in encoder_mask for the atomic case, but that should be perfectly fine since we can assume the old state itself had no conflicting encoder assignments. I think it could use a few high levelish comments around the loops to explain what they are supposed to do, somewhat like you had in update_output_state(). > > This boils down to: > > if (stealing encoder from existing connector not part of state) > if (atomic) return -EINVAL; > else > // disable connector and possibly crtc > > ~Maarten -- Ville Syrjälä Intel OTC
[PATCH 0/2] drm/vc4: Fixes for Raspberry Pi 3
Hi, On 1 March 2016 at 01:52, Eric Anholt wrote: > These are for fixing the vc4 driver on the Pi 3. Note that patch 2 > will also be necessary for fixing HPD on the Pi2, which we've been > carrying downstream patches to work around until now. Indeed. Having cherry-picked 80032d2e61 and added ACTIVE_LOW to the bcm2836-rpi-2-b DT, I now get HPD reported correctly. I think it might still need work: on RPi2 again, DDC fails on boot (the same BCM2835_I2C_S_ERR bit being set, i.e. 'i2c transfer failed: 100'), and does work after a hotplug cycle. But the machine then immediately hard-hangs - no serial console - after cat /sys/class/drm/card0-HDMI-A-1/edid. On the grounds that the VC4 node isn't yet in upstream DT though, and this _does_ indeed fix HPD: Tested-by: Daniel Stone Cheers, Daniel
Alternative binding proposal for tda998x audio (Was: Re: [PATCH RFC v5 4/8] drm/i2c: tda998x: Add support of a DT graph of ports)
On 03/01/16 18:16, Jean-Francois Moine wrote: > On Tue, 1 Mar 2016 17:51:09 +0200 > Jyri Sarha wrote: > >> I know that it works, I have used it myself until now, but it is not >> needed and there is no driver that parses audio port endpoints. I see no >> point specifying something in the binding that is not used and there no >> specific plan to ever use it. >> >> AFAIU my proposed binding should work equally well with simple-card, >> with or without multi-codec support. > > As told many times, the simple card is a pure Linux specific entity. > It does not describe any hardware. It should not appear in a DT, or, > if it does, its compatible should be "linux, simple-audio-card". > Then, how can the other OSs know the links between the audio > devices and the audio encoders/connectors? > I understand the short comings of simple-card and it's binding. However, the binding is documented and it is feasible to extract the audio connections from a simple-card binding too. In fact it models the I2S connections better than straight out of the box graph binding. Actually a graph is not the best way describe an i2s-bus with multiple DAIs (codec or CPU) connected to it. > On the other way, the audio graph does not impose any particular > software design. It just describes the links between the different > hardware components and each OS is free to implement its own layout. > That is true. In the most narrow sense the i2s protocol details, or even TDM time-slot selections should not be in the dtb. However, is not feasible to write a generic machine driver that would deduce the ideal audio configuration just based on the i2s wiring between the audio components simply because that is not enough information*. So to put it simply the simple-card is not the perfect solution for the problem, but even with its flaws it is better than straight out of the box graph binding, and it is still entirely feasible to extract all needed information for any audio implementation from that binding. Still even with my proposed binding there is nothing that prevents adding the graph binding on top of that if it is ever needed. Best regards, Jyri * With a complete set of information of all audio wiring and component capabilities, including the analog only components, it would probably be possible to deduce a generic configuration that would work in the most common - simple cases, but let's not go there now.
[PATCH v12 10/14] clk: mediatek: make dpi0_sel propagate rate changes
On 03/01, Philipp Zabel wrote: > This mux is supposed to select a fitting divider after the PLL > is already set to the correct rate. > > Signed-off-by: Philipp Zabel > Acked-by: James Liao > --- Acked-by: Stephen Boyd -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
Alternative binding proposal for tda998x audio (Was: Re: [PATCH RFC v5 4/8] drm/i2c: tda998x: Add support of a DT graph of ports)
On Tue, 1 Mar 2016 20:29:17 +0200 Jyri Sarha wrote: > I understand the short comings of simple-card and it's binding. However, > the binding is documented and it is feasible to extract the audio > connections from a simple-card binding too. In fact it models the I2S > connections better than straight out of the box graph binding. Actually > a graph is not the best way describe an i2s-bus with multiple DAIs > (codec or CPU) connected to it. I still don't understand your problem. You want something like: audio-ports = < TDA998x_SPDIF 0x04 TDA998x_I2S 0x03>; and the graph definition would be: port at 03 { reg = <0x03>; port-type = "audio-i2s"; ... }; port at 04 { reg = <0x04>; port-type = "audio-spdif"; ... }; Apart the syntax, I don't really see the difference. -- Ken ar c'hentañ| ** Breizh ha Linux atav! ** Jef | http://moinejf.free.fr/
[PATCH 1/2] drm/amdgpu: Fix error handling in amdgpu_flip_work_func.
The patch e1d09dc0ccc6: "drm/amdgpu: Don't hang in amdgpu_flip_work_func on disabled crtc." from Feb 19, 2016, leads to the following static checker warning, as reported by Dan Carpenter in https://lists.freedesktop.org/archives/dri-devel/2016-February/101987.html drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:127 amdgpu_flip_work_func() warn: should this be 'repcnt == -1' drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:136 amdgpu_flip_work_func() error: double unlock 'spin_lock:&crtc->dev->event_lock' drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:136 amdgpu_flip_work_func() error: double unlock 'irqsave:flags' This patch fixes both reported problems: Change post-decrement of repcnt to pre-decrement, so it can't underflow anymore, but still performs up to three repetitions - three is the maximum one could expect in practice. Move the spin_unlock_irqrestore to where it actually belongs. Reported-by: Dan Carpenter Signed-off-by: Mario Kleiner Cc: # 4.4+ Cc: Michel Dänzer Cc: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 8297bc3..1846d65 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -96,7 +96,7 @@ static void amdgpu_flip_work_func(struct work_struct *__work) * In practice this won't execute very often unless on very fast * machines because the time window for this to happen is very small. */ - while (amdgpuCrtc->enabled && repcnt--) { + while (amdgpuCrtc->enabled && --repcnt) { /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank * start in hpos, and to the "fudged earlier" vblank start in * vpos. @@ -112,13 +112,13 @@ static void amdgpu_flip_work_func(struct work_struct *__work) break; /* Sleep at least until estimated real start of hw vblank */ - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); if (min_udelay > vblank->framedur_ns / 2000) { /* Don't wait ridiculously long - something is wrong */ repcnt = 0; break; } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); usleep_range(min_udelay, 2 * min_udelay); spin_lock_irqsave(&crtc->dev->event_lock, flags); }; -- 1.9.1
[PATCH 2/2] drm/radeon: Fix error handling in radeon_flip_work_func.
This is a port of the patch "drm/amdgpu: Fix error handling in amdgpu_flip_work_func." to fix the following problem for radeon as well which was reported against amdgpu: The patch e1d09dc0ccc6: "drm/amdgpu: Don't hang in amdgpu_flip_work_func on disabled crtc." from Feb 19, 2016, leads to the following static checker warning, as reported by Dan Carpenter in https://lists.freedesktop.org/archives/dri-devel/2016-February/101987.html drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:127 amdgpu_flip_work_func() warn: should this be 'repcnt == -1' drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:136 amdgpu_flip_work_func() error: double unlock 'spin_lock:&crtc->dev->event_lock' drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:136 amdgpu_flip_work_func() error: double unlock 'irqsave:flags' This patch fixes both reported problems: Change post-decrement of repcnt to pre-decrement, so it can't underflow anymore, but still performs up to three repetitions - three is the maximum one could expect in practice. Move the spin_unlock_irqrestore to where it actually belongs. Reported-by: Dan Carpenter Signed-off-by: Mario Kleiner Cc: # 4.4+ Cc: Michel Dänzer Cc: Alex Deucher --- drivers/gpu/drm/radeon/radeon_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1fab4b9..bfcef4d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -455,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work) * In practice this won't execute very often unless on very fast * machines because the time window for this to happen is very small. */ - while (radeon_crtc->enabled && repcnt--) { + while (radeon_crtc->enabled && --repcnt) { /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank * start in hpos, and to the "fudged earlier" vblank start in * vpos. @@ -471,13 +471,13 @@ static void radeon_flip_work_func(struct work_struct *__work) break; /* Sleep at least until estimated real start of hw vblank */ - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); if (min_udelay > vblank->framedur_ns / 2000) { /* Don't wait ridiculously long - something is wrong */ repcnt = 0; break; } + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); usleep_range(min_udelay, 2 * min_udelay); spin_lock_irqsave(&crtc->dev->event_lock, flags); }; -- 1.9.1
drm/amdgpu: Don't hang in amdgpu_flip_work_func on disabled crtc.
On 02/29/2016 09:10 PM, Dan Carpenter wrote: > Hello Mario Kleiner, > > The patch e1d09dc0ccc6: "drm/amdgpu: Don't hang in > amdgpu_flip_work_func on disabled crtc." from Feb 19, 2016, leads to > the following static checker warning: > > drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:127 amdgpu_flip_work_func() > warn: should this be 'repcnt == -1' > drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:136 amdgpu_flip_work_func() > error: double unlock 'spin_lock:&crtc->dev->event_lock' > drivers/gpu/drm/amd/amdgpu/amdgpu_display.c:136 amdgpu_flip_work_func() > error: double unlock 'irqsave:flags' > > > drivers/gpu/drm/amd/amdgpu/amdgpu_display.c > 64 static void amdgpu_flip_work_func(struct work_struct *__work) > 65 { > 66 struct amdgpu_flip_work *work = > 67 container_of(__work, struct amdgpu_flip_work, > flip_work); > 68 struct amdgpu_device *adev = work->adev; > 69 struct amdgpu_crtc *amdgpuCrtc = > adev->mode_info.crtcs[work->crtc_id]; > 70 > 71 struct drm_crtc *crtc = &amdgpuCrtc->base; > 72 unsigned long flags; > 73 unsigned i, repcnt = 4; > 74 int vpos, hpos, stat, min_udelay = 0; > 75 struct drm_vblank_crtc *vblank = > &crtc->dev->vblank[work->crtc_id]; > 76 > 77 if (amdgpu_flip_handle_fence(work, &work->excl)) > 78 return; > 79 > 80 for (i = 0; i < work->shared_count; ++i) > 81 if (amdgpu_flip_handle_fence(work, &work->shared[i])) > 82 return; > 83 > 84 /* We borrow the event spin lock for protecting flip_status > */ > 85 spin_lock_irqsave(&crtc->dev->event_lock, flags); > 86 > 87 /* If this happens to execute within the "virtually > extended" vblank > 88 * interval before the start of the real vblank interval > then it needs > 89 * to delay programming the mmio flip until the real vblank > is entered. > 90 * This prevents completing a flip too early due to the way > we fudge > 91 * our vblank counter and vblank timestamps in order to work > around the > 92 * problem that the hw fires vblank interrupts before actual > start of > 93 * vblank (when line buffer refilling is done for a frame). > It > 94 * complements the fudging logic in > amdgpu_get_crtc_scanoutpos() for > 95 * timestamping and amdgpu_get_vblank_counter_kms() for > vblank counts. > 96 * > 97 * In practice this won't execute very often unless on very > fast > 98 * machines because the time window for this to happen is > very small. > 99 */ > 100 while (amdgpuCrtc->enabled && repcnt--) { > > Exists the loop with spin_lock held and repcnt == -1. > > > 101 /* GET_DISTANCE_TO_VBLANKSTART returns distance to > real vblank > 102 * start in hpos, and to the "fudged earlier" vblank > start in > 103 * vpos. > 104 */ > 105 stat = amdgpu_get_crtc_scanoutpos(adev->ddev, > work->crtc_id, > 106 > GET_DISTANCE_TO_VBLANKSTART, > 107&vpos, &hpos, > NULL, NULL, > 108&crtc->hwmode); > 109 > 110 if ((stat & (DRM_SCANOUTPOS_VALID | > DRM_SCANOUTPOS_ACCURATE)) != > 111 (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE) > || > 112 !(vpos >= 0 && hpos <= 0)) > 113 break; > 114 > 115 /* Sleep at least until estimated real start of hw > vblank */ > 116 spin_unlock_irqrestore(&crtc->dev->event_lock, > flags); > 117 min_udelay = (-hpos + 1) * max(vblank->linedur_ns / > 1000, 5); > 118 if (min_udelay > vblank->framedur_ns / 2000) { > 119 /* Don't wait ridiculously long - something > is wrong */ > 120 repcnt = 0; > > Exit with spin_lock released and repcnt == 0. > > 121 break; > 122 } > 123 usleep_range(min_udelay, 2 * min_udelay); > 124 spin_lock_irqsave(&crtc->dev->event_lock, flags); > 125 }; > 126 > 127 if (!repcnt) > ^^ > Assumes exit with zero. > > 128 DRM_DEBUG_DRIVER("Delay problem on crtc %d: > min_udelay %d, " > 129 "framedur %d, linedur %d, stat %d, > vpos %d
[PATCH] drm: rcar-du: clarify vsp dependency
Hi Arnd, Thank you for the patch. On Friday 26 February 2016 12:52:20 Arnd Bergmann wrote: > The VSP1 compositor code in DRM links against the respective V4L > driver, but the dependency is not expressed correctly in Kconfig, > which leads to a build error when the DRM driver is built-in > and the V4L driver is a module: > > drivers/gpu/built-in.o: In function `rcar_du_vsp_plane_atomic_update': > rcar-du/rcar_du_vsp.c:183: undefined reference to `vsp1_du_atomic_update' > > This patch avoids the problem by ensuring that the DRM VSP code can > only be enabled if the V4L driver is linked into the kernel, or > both are loadable modules. > > Signed-off-by: Arnd Bergmann > Fixes: 6d62ef3ac30b ("drm: rcar-du: Expose the VSP1 compositor through KMS > planes") Acked-by: Laurent Pinchart Dave, could you please queue this for v4.6 ? > --- > drivers/gpu/drm/rcar-du/Kconfig | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/rcar-du/Kconfig > b/drivers/gpu/drm/rcar-du/Kconfig index 1f10fa0928b4..eb1e6d5cfed9 100644 > --- a/drivers/gpu/drm/rcar-du/Kconfig > +++ b/drivers/gpu/drm/rcar-du/Kconfig > @@ -27,6 +27,6 @@ config DRM_RCAR_LVDS > config DRM_RCAR_VSP > bool "R-Car DU VSP Compositor Support" > depends on DRM_RCAR_DU > - depends on VIDEO_RENESAS_VSP1 > + depends on VIDEO_RENESAS_VSP1=y || (VIDEO_RENESAS_VSP1 && DRM_RCAR_DU=m) > help > Enable support to expose the R-Car VSP Compositor as KMS planes. -- Regards, Laurent Pinchart
[PATCH] drm/panel: simple: fix g121x1_l03 hsync/vsync polarity
Set hsync/vsync to active low for g121x1_l03 panel to match the recommended setting in datasheet. Signed-off-by: Akshay Bhat --- drivers/gpu/drm/panel/panel-simple.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 2164c99..5d11322 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -847,6 +847,7 @@ static const struct drm_display_mode innolux_g121x1_l03_mode = { .vsync_end = 768 + 38 + 1, .vtotal = 768 + 38 + 1 + 0, .vrefresh = 60, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, }; static const struct panel_desc innolux_g121x1_l03 = { -- 2.7.2
[PATCH 4.4 193/342] drm/nouveau/display: Enable vblank irqs after display engine is on again.
4.4-stable review patch. If anyone has any objections, please let me know. -- From: Mario Kleiner commit ff683df7bf34f90766a50c7e7454e219aef2710e upstream. In the display resume path, move the calls to drm_vblank_on() after the point when the display engine is running again. Since changes were made to drm_update_vblank_count() in Linux 4.4+ to emulate hw vblank counters via vblank timestamping, the function drm_vblank_on() now needs working high precision vblank timestamping and therefore working scanout position queries at time of call. These don't work before the display engine gets restarted, causing miscalculation of vblank counter increments and thereby large forward jumps in vblank count at display resume. These jumps can cause client hangs on resume, or desktop hangs in the case of composited desktops. Fix this Linux 4.4 regression by reordering calls accordingly. Signed-off-by: Mario Kleiner Cc: Ben Skeggs Cc: ville.syrjala at linux.intel.com Cc: daniel.vetter at ffwll.ch Cc: dri-devel at lists.freedesktop.org Reviewed-by: Daniel Vetter Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/nouveau/nouveau_display.c |8 1 file changed, 4 insertions(+), 4 deletions(-) --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -634,10 +634,6 @@ nouveau_display_resume(struct drm_device nv_crtc->lut.depth = 0; } - /* Make sure that drm and hw vblank irqs get resumed if needed. */ - for (head = 0; head < dev->mode_config.num_crtc; head++) - drm_vblank_on(dev, head); - /* This should ensure we don't hit a locking problem when someone * wakes us up via a connector. We should never go into suspend * while the display is on anyways. @@ -647,6 +643,10 @@ nouveau_display_resume(struct drm_device drm_helper_resume_force_mode(dev); + /* Make sure that drm and hw vblank irqs get resumed if needed. */ + for (head = 0; head < dev->mode_config.num_crtc; head++) + drm_vblank_on(dev, head); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
[PATCH 4.4 232/342] drm: Fix treatment of drm_vblank_offdelay in drm_vblank_on() (v2)
4.4-stable review patch. If anyone has any objections, please let me know. -- From: Mario Kleiner commit bb74fc1bf3072bd3ab4ed5f43afd287a63baf2d7 upstream. drm_vblank_offdelay can have three different types of values: < 0 is to be always treated the same as dev->vblank_disable_immediate = 0 is to be treated as "never disable vblanks" > 0 is to be treated as disable immediate if kms driver wants it that way via dev->vblank_disable_immediate. Otherwise it is a disable timeout in msecs. This got broken in Linux 3.18+ for the implementation of drm_vblank_on. If the user specified a value of zero which should always reenable vblank irqs in this function, a kms driver could override the users choice by setting vblank_disable_immediate to true. This patch fixes the regression and keeps the user in control. v2: Only reenable vblank if there are clients left or the user requested to "never disable vblanks" via offdelay 0. Enabling vblanks even in the "delayed disable" case (offdelay > 0) was specifically added by Ville in commit cd19e52aee922 ("drm: Kick start vblank interrupts at drm_vblank_on()"), but after discussion it turns out that this was done by accident. Citing Ville: "I think it just ended up as a mess due to changing some of the semantics of offdelay<0 vs. offdelay==0 vs. disable_immediate during the review of the series. So yeah, given how drm_vblank_put() works now, I'd just make this check for offdelay==0." Signed-off-by: Mario Kleiner Reviewed-by: Daniel Vetter Cc: michel at daenzer.net Cc: vbabka at suse.cz Cc: ville.syrjala at linux.intel.com Cc: daniel.vetter at ffwll.ch Cc: dri-devel at lists.freedesktop.org Cc: alexander.deucher at amd.com Cc: christian.koenig at amd.com Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_irq.c |3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -1494,8 +1494,7 @@ void drm_vblank_on(struct drm_device *de * re-enable interrupts if there are users left, or the * user wishes vblank interrupts to be enabled all the time. */ - if (atomic_read(&vblank->refcount) != 0 || - (!dev->vblank_disable_immediate && drm_vblank_offdelay == 0)) + if (atomic_read(&vblank->refcount) != 0 || drm_vblank_offdelay == 0) WARN_ON(drm_vblank_enable(dev, pipe)); spin_unlock_irqrestore(&dev->vbl_lock, irqflags); }
[PATCH 4.4 231/342] drm: Fix drm_vblank_pre/post_modeset regression from Linux 4.4
4.4-stable review patch. If anyone has any objections, please let me know. -- From: Mario Kleiner commit c61934ed9a0e3911a9935df26858726a7ec35ec0 upstream. Changes to drm_update_vblank_count() in Linux 4.4 broke the behaviour of the pre/post modeset functions as the new update code doesn't deal with hw vblank counter resets inbetween calls to drm_vblank_pre_modeset an drm_vblank_post_modeset, as it should. This causes mistreatment of such hw counter resets as counter wraparound, and thereby large forward jumps of the software vblank counter which in turn cause vblank event dispatching and vblank waits to fail/hang --> userspace clients hang. This symptom was reported on radeon-kms to cause a infinite hang of KDE Plasma 5 shell's login procedure, preventing users from logging in. Fix this by detecting when drm_update_vblank_count() is called inside a pre->post modeset interval. If so, clamp valid vblank increments to the safe values 0 and 1, pretty much restoring the update behavior of the old update code of Linux 4.3 and earlier. Also reset the last recorded hw vblank count at call to drm_vblank_post_modeset() to be safe against hw that after modesetting, dpms on etc. only fires its first vblank irq after drm_vblank_post_modeset() was already called. Reported-by: Vlastimil Babka Signed-off-by: Mario Kleiner Reviewed-by: Daniel Vetter Tested-by: Vlastimil Babka Cc: michel at daenzer.net Cc: vbabka at suse.cz Cc: ville.syrjala at linux.intel.com Cc: daniel.vetter at ffwll.ch Cc: dri-devel at lists.freedesktop.org Cc: alexander.deucher at amd.com Cc: christian.koenig at amd.com Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/drm_irq.c | 16 1 file changed, 16 insertions(+) --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -222,6 +222,21 @@ static void drm_update_vblank_count(stru } /* +* Within a drm_vblank_pre_modeset - drm_vblank_post_modeset +* interval? If so then vblank irqs keep running and it will likely +* happen that the hardware vblank counter is not trustworthy as it +* might reset at some point in that interval and vblank timestamps +* are not trustworthy either in that interval. Iow. this can result +* in a bogus diff >> 1 which must be avoided as it would cause +* random large forward jumps of the software vblank counter. +*/ + if (diff > 1 && (vblank->inmodeset & 0x2)) { + DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u" + " due to pre-modeset.\n", pipe, diff); + diff = 1; + } + + /* * FIMXE: Need to replace this hack with proper seqlocks. * * Restrict the bump of the software vblank counter to a safe maximum @@ -1575,6 +1590,7 @@ void drm_vblank_post_modeset(struct drm_ if (vblank->inmodeset) { spin_lock_irqsave(&dev->vbl_lock, irqflags); dev->vblank_disable_allowed = true; + drm_reset_vblank_timestamp(dev, pipe); spin_unlock_irqrestore(&dev->vbl_lock, irqflags); if (vblank->inmodeset & 0x2)
[PATCH 4.4 230/342] drm: Prevent vblank counter bumps > 1 with active vblank clients. (v2)
4.4-stable review patch. If anyone has any objections, please let me know. -- From: Mario Kleiner commit 99b8e71597fadd6b2ac85e6e10f221f79dd9c1c1 upstream. This fixes a regression introduced by the new drm_update_vblank_count() implementation in Linux 4.4: Restrict the bump of the software vblank counter in drm_update_vblank_count() to a safe maximum value of +1 whenever there is the possibility that concurrent readers of vblank timestamps could be active at the moment, as the current implementation of the timestamp caching and updating is not safe against concurrent readers for calls to store_vblank() with a bump of anything but +1. A bump != 1 would very likely return corrupted timestamps to userspace, because the same slot in the cache could be concurrently written by store_vblank() and read by one of those readers in a non-atomic fashion and without the read-retry logic detecting this collision. Concurrent readers can exist while drm_update_vblank_count() is called from the drm_vblank_off() or drm_vblank_on() functions or other non-vblank- irq callers. However, all those calls are happening with the vbl_lock locked thereby preventing a drm_vblank_get(), so the vblank refcount can't increase while drm_update_vblank_count() is executing. Therefore a zero vblank refcount during execution of that function signals that is safe for arbitrary counter bumps if called from outside vblank irq, whereas a non-zero count is not safe. Whenever the function is called from vblank irq, we have to assume concurrent readers could show up any time during its execution, even if the refcount is currently zero, as vblank irqs are usually only enabled due to the presence of readers, and because when it is called from vblank irq it can't hold the vbl_lock to protect it from sudden bumps in vblank refcount. Therefore also restrict bumps to +1 when the function is called from vblank irq. Such bumps of more than +1 can happen at other times than reenabling vblank irqs, e.g., when regular vblank interrupts get delayed by more than 1 frame due to long held locks, long irq off periods, realtime preemption on RT kernels, or system management interrupts. A better solution would be to rewrite the timestamp caching to use full seqlocks to allow concurrent writes and reads for arbitrary vblank counter increments. v2: Add code comment that this is essentially a hack and should be replaced by a full seqlock implementation for caching of timestamps. Signed-off-by: Mario Kleiner Reviewed-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman Cc: michel at daenzer.net Cc: vbabka at suse.cz Cc: ville.syrjala at linux.intel.com Cc: daniel.vetter at ffwll.ch Cc: dri-devel at lists.freedesktop.org Cc: alexander.deucher at amd.com Cc: christian.koenig at amd.com Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_irq.c | 43 +++ 1 file changed, 43 insertions(+) --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -221,6 +221,49 @@ static void drm_update_vblank_count(stru diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0; } + /* +* FIMXE: Need to replace this hack with proper seqlocks. +* +* Restrict the bump of the software vblank counter to a safe maximum +* value of +1 whenever there is the possibility that concurrent readers +* of vblank timestamps could be active at the moment, as the current +* implementation of the timestamp caching and updating is not safe +* against concurrent readers for calls to store_vblank() with a bump +* of anything but +1. A bump != 1 would very likely return corrupted +* timestamps to userspace, because the same slot in the cache could +* be concurrently written by store_vblank() and read by one of those +* readers without the read-retry logic detecting the collision. +* +* Concurrent readers can exist when we are called from the +* drm_vblank_off() or drm_vblank_on() functions and other non-vblank- +* irq callers. However, all those calls to us are happening with the +* vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount +* can't increase while we are executing. Therefore a zero refcount at +* this point is safe for arbitrary counter bumps if we are called +* outside vblank irq, a non-zero count is not 100% safe. Unfortunately +* we must also accept a refcount of 1, as whenever we are called from +* drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and +* we must let that one pass through in order to not lose vblank counts +* during vblank irq off - which would completely defeat the whole +* point of this routine. +* +* Whenever we are called from vblank irq, we have to assume concurrent +* readers exist or can show up any time during our execution, eve
[PATCH] drm/ast: Fix incorrect register check for DRAM width
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 02/26/2016 03:29 PM, Timothy Pearson wrote: > During DRAM initialization on certain ASpeed devices, an incorrect > bit (bit 10) was checked in the "SDRAM Bus Width Status" register > to determine DRAM width. > > Query bit 6 instead in accordance with the Aspeed AST2050 datasheet v1.05. > > Signed-off-by: Timothy Pearson > --- > drivers/gpu/drm/ast/ast_main.c |2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c > index 9759009..b1480ac 100644 > --- a/drivers/gpu/drm/ast/ast_main.c > +++ b/drivers/gpu/drm/ast/ast_main.c > @@ -227,7 +227,7 @@ static int ast_get_dram_info(struct drm_device *dev) > } while (ast_read32(ast, 0x1) != 0x01); > data = ast_read32(ast, 0x10004); > > - if (data & 0x400) > + if (data & 0x40) > ast->dram_bus_width = 16; > else > ast->dram_bus_width = 32; Just wanted to give this a bump since I have not received any feedback on it. Thanks! - -- Timothy Pearson Raptor Engineering +1 (415) 727-8645 (direct line) +1 (512) 690-0200 (switchboard) http://www.raptorengineeringinc.com -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iQEcBAEBAgAGBQJW1eZsAAoJEK+E3vEXDOFbusEH/2HXEJ4MfTsV5FRmXQpqv4rh iqGbd/whbOl9HAwWwz1DgfDIoqjBvBUlrq4C/UEmkFIVo5cqZQQsUIHejsz/GEIx 2mpf1pTIaNnW8oK6w8QX2wxFiV4XOUallOHh+OPmUTZQFpDiJH7MgqWhZ7HNEsRi lyjYILfPw5Q1cRHKxCn+IPGgStPDr6ds5EbAlNNZKTgdRuUoPLW3LLAyZ6Gtjkwr FVSe4uIiLC1/HNlrhryFvsAPA6N5hUqFDxAZ7pLFKoRLJpteJnhr5tBJLnwScZlN 6zYZRmDieHHIomFK462SGo8lhyxc8bnbJkYuEKvNvOzdI7B4rriCUMWpIgw1ISg= =JWPN -END PGP SIGNATURE-