From: gouhao gouhao@uniontech.com
Fix hibmc did not get edid.
issue: https://gitee.com/openeuler/kernel/issues/I469VQ
gouhao (5): drm-Split-out-drm_probe_helper.h drm-Add-ddc-link-in-sysfs-created-by-drm_connector drm-Add-drm_connector_init-variant-with-ddc drm/hisilicon: Support i2c driver algorithms for bit-shift adapters drm/hisilicon: Features to support reading resolutions from EDID
drivers/gpu/drm/drm_connector.c | 35 +++++++ drivers/gpu/drm/drm_sysfs.c | 8 ++ drivers/gpu/drm/hisilicon/hibmc/Makefile | 3 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 26 +++++ .../gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c | 99 +++++++++++++++++++ .../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 55 ++++++++--- include/drm/drm_connector.h | 18 ++++ include/drm/drm_probe_helper.h | 27 +++++ 8 files changed, 256 insertions(+), 15 deletions(-) create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c create mode 100644 include/drm/drm_probe_helper.h
From: gouhao gouhao@uniontech.com
mainline inclusion from mainline-v5.14.0-rc7 commit fcd70cd36b9bf697122538c9e38e8cf954b2342b category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I469VQ CVE: NA
---------------------------------------------
Having the probe helper stuff (which pretty much everyone needs) in the drm_crtc_helper.h file (which atomic drivers should never need) is confusing. Split them out.
To make sure I actually achieved the goal here I went through all drivers. And indeed, all atomic drivers are now free of drm_crtc_helper.h includes.
v2: Make it compile. There was so much compile fail on arm drivers that I figured I'll better not include any of the acks on v1.
v3: Massive rebase because i915 has lost a lot of drmP.h includes, but not all: Through drm_crtc_helper.h > drm_modeset_helper.h -> drmP.h there was still one, which this patch largely removes. Which means rolling out lots more includes all over.
This will also conflict with ongoing drmP.h cleanup by others I expect.
v3: Rebase on top of atomic bochs.
v4: Review from Laurent for bridge/rcar/omap/shmob/core bits: - (re)move some of the added includes, use the better include files in other places (all suggested from Laurent adopted unchanged). - sort alphabetically
v5: Actually try to sort them, and while at it, sort all the ones I touch.
v6: Rebase onto i915 changes.
v7: Rebase once more.
Acked-by: Harry Wentland harry.wentland@amd.com Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Sam Ravnborg sam@ravnborg.org Cc: Jani Nikula jani.nikula@linux.intel.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Acked-by: Rodrigo Vivi rodrigo.vivi@intel.com Acked-by: Benjamin Gaignard benjamin.gaignard@linaro.org Acked-by: Jani Nikula jani.nikula@intel.com Acked-by: Neil Armstrong narmstrong@baylibre.com Acked-by: Oleksandr Andrushchenko oleksandr_andrushchenko@epam.com Acked-by: CK Hu ck.hu@mediatek.com Acked-by: Alex Deucher alexander.deucher@amd.com Acked-by: Sam Ravnborg sam@ravnborg.org Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Acked-by: Liviu Dudau liviu.dudau@arm.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: linux-arm-kernel@lists.infradead.org Cc: virtualization@lists.linux-foundation.org Cc: etnaviv@lists.freedesktop.org Cc: linux-samsung-soc@vger.kernel.org Cc: intel-gfx@lists.freedesktop.org Cc: linux-mediatek@lists.infradead.org Cc: linux-amlogic@lists.infradead.org Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Cc: nouveau@lists.freedesktop.org Cc: spice-devel@lists.freedesktop.org Cc: amd-gfx@lists.freedesktop.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-rockchip@lists.infradead.org Cc: linux-stm32@st-md-mailman.stormreply.com Cc: linux-tegra@vger.kernel.org Cc: xen-devel@lists.xen.org Link: https://patchwork.freedesktop.org/patch/msgid/20190117210334.13234-1-daniel....
Signed-off-by: gouhao gouhao@uniontech.com
--- include/drm/drm_probe_helper.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 include/drm/drm_probe_helper.h
diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h new file mode 100644 index 000000000..8d3ed2834 --- /dev/null +++ b/include/drm/drm_probe_helper.h @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT + +#ifndef __DRM_PROBE_HELPER_H__ +#define __DRM_PROBE_HELPER_H__ + +#include <linux/types.h> + +struct drm_connector; +struct drm_device; +struct drm_modeset_acquire_ctx; + +int drm_helper_probe_single_connector_modes(struct drm_connector + *connector, uint32_t maxX, + uint32_t maxY); +int drm_helper_probe_detect(struct drm_connector *connector, + struct drm_modeset_acquire_ctx *ctx, + bool force); +void drm_kms_helper_poll_init(struct drm_device *dev); +void drm_kms_helper_poll_fini(struct drm_device *dev); +bool drm_helper_hpd_irq_event(struct drm_device *dev); +void drm_kms_helper_hotplug_event(struct drm_device *dev); + +void drm_kms_helper_poll_disable(struct drm_device *dev); +void drm_kms_helper_poll_enable(struct drm_device *dev); +bool drm_kms_helper_is_poll_worker(void); + +#endif
Hi Gou Hao,
Thanks for your patches.
On 2021/9/17 11:41, Gou Hao wrote:
From: gouhao gouhao@uniontech.com
Please do not change the author. The 'From:' line should be the original author.
mainline inclusion from mainline-v5.14.0-rc7 commit fcd70cd36b9bf697122538c9e38e8cf954b2342b category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I469VQ CVE: NA
Having the probe helper stuff (which pretty much everyone needs) in the drm_crtc_helper.h file (which atomic drivers should never need) is confusing. Split them out.
To make sure I actually achieved the goal here I went through all drivers. And indeed, all atomic drivers are now free of drm_crtc_helper.h includes.
v2: Make it compile. There was so much compile fail on arm drivers that I figured I'll better not include any of the acks on v1.
v3: Massive rebase because i915 has lost a lot of drmP.h includes, but not all: Through drm_crtc_helper.h > drm_modeset_helper.h -> drmP.h there was still one, which this patch largely removes. Which means rolling out lots more includes all over.
This will also conflict with ongoing drmP.h cleanup by others I expect.
v3: Rebase on top of atomic bochs.
v4: Review from Laurent for bridge/rcar/omap/shmob/core bits:
- (re)move some of the added includes, use the better include files in other places (all suggested from Laurent adopted unchanged).
- sort alphabetically
v5: Actually try to sort them, and while at it, sort all the ones I touch.
v6: Rebase onto i915 changes.
v7: Rebase once more.
Acked-by: Harry Wentland harry.wentland@amd.com Acked-by: Sam Ravnborg sam@ravnborg.org Cc: Sam Ravnborg sam@ravnborg.org Cc: Jani Nikula jani.nikula@linux.intel.com Cc: Laurent Pinchart laurent.pinchart@ideasonboard.com Acked-by: Rodrigo Vivi rodrigo.vivi@intel.com Acked-by: Benjamin Gaignard benjamin.gaignard@linaro.org Acked-by: Jani Nikula jani.nikula@intel.com Acked-by: Neil Armstrong narmstrong@baylibre.com Acked-by: Oleksandr Andrushchenko oleksandr_andrushchenko@epam.com Acked-by: CK Hu ck.hu@mediatek.com Acked-by: Alex Deucher alexander.deucher@amd.com Acked-by: Sam Ravnborg sam@ravnborg.org Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Acked-by: Liviu Dudau liviu.dudau@arm.com Signed-off-by: Daniel Vetter daniel.vetter@intel.com Cc: linux-arm-kernel@lists.infradead.org Cc: virtualization@lists.linux-foundation.org Cc: etnaviv@lists.freedesktop.org Cc: linux-samsung-soc@vger.kernel.org Cc: intel-gfx@lists.freedesktop.org Cc: linux-mediatek@lists.infradead.org Cc: linux-amlogic@lists.infradead.org Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Cc: nouveau@lists.freedesktop.org Cc: spice-devel@lists.freedesktop.org Cc: amd-gfx@lists.freedesktop.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-rockchip@lists.infradead.org Cc: linux-stm32@st-md-mailman.stormreply.com Cc: linux-tegra@vger.kernel.org Cc: xen-devel@lists.xen.org Link: https://patchwork.freedesktop.org/patch/msgid/20190117210334.13234-1-daniel....
Signed-off-by: gouhao gouhao@uniontech.com
include/drm/drm_probe_helper.h | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 include/drm/drm_probe_helper.h
diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h new file mode 100644 index 000000000..8d3ed2834 --- /dev/null +++ b/include/drm/drm_probe_helper.h @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT
+#ifndef __DRM_PROBE_HELPER_H__ +#define __DRM_PROBE_HELPER_H__
+#include <linux/types.h>
+struct drm_connector; +struct drm_device; +struct drm_modeset_acquire_ctx;
+int drm_helper_probe_single_connector_modes(struct drm_connector
*connector, uint32_t maxX,
uint32_t maxY);
+int drm_helper_probe_detect(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx,
bool force);
+void drm_kms_helper_poll_init(struct drm_device *dev); +void drm_kms_helper_poll_fini(struct drm_device *dev); +bool drm_helper_hpd_irq_event(struct drm_device *dev); +void drm_kms_helper_hotplug_event(struct drm_device *dev);
+void drm_kms_helper_poll_disable(struct drm_device *dev); +void drm_kms_helper_poll_enable(struct drm_device *dev); +bool drm_kms_helper_is_poll_worker(void);
+#endif
From: gouhao gouhao@uniontech.com
mainline inclusion from mainline-v5.14.0-rc7 commit e1a29c6c59553d80a8e17d63494c65a13fb8e241 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I469VQ CVE: NA
--------------------------------
Add generic code which creates symbolic links in sysfs, pointing to ddc interface used by a particular video output. For example:
ls -l /sys/class/drm/card0-HDMI-A-1/ddc lrwxrwxrwx 1 root root 0 Jun 24 10:42 /sys/class/drm/card0-HDMI-A-1/ddc \ -> ../../../../soc/13880000.i2c/i2c-2
This makes it easy for user to associate a display with its ddc adapter and use e.g. ddcutil to control the chosen monitor.
This patch adds an i2c_adapter pointer to struct drm_connector. Particular drivers can then use it instead of using their own private instance. If a connector contains a ddc, then create a symbolic link in sysfs.
Signed-off-by: Andrzej Pietrasiewicz andrzej.p@collabora.com Acked-by: Daniel Vetter daniel.vetter@ffwll.ch Reviewed-by: Andrzej Hajda a.hajda@samsung.com Reviewed-by: Emil Velikov emil.velikov@collabora.com Reviewed-by: Sam Ravnborg sam@ravnborg.org Signed-off-by: Neil Armstrong narmstrong@baylibre.com Link: https://patchwork.freedesktop.org/patch/msgid/d470def6cd661b777faeee67b5838a...
Signed-off-by: gouhao gouhao@uniontech.com --- drivers/gpu/drm/drm_sysfs.c | 8 ++++++++ include/drm/drm_connector.h | 11 +++++++++++ 2 files changed, 19 insertions(+)
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index ecb7b3300..52879b001 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -15,6 +15,7 @@ #include <linux/device.h> #include <linux/kdev_t.h> #include <linux/gfp.h> +#include <linux/i2c.h> #include <linux/err.h> #include <linux/export.h>
@@ -287,6 +288,9 @@ int drm_sysfs_connector_add(struct drm_connector *connector) /* Let userspace know we have a new connector */ drm_sysfs_hotplug_event(dev);
+ if (connector->ddc) + return sysfs_create_link(&connector->kdev->kobj, + &connector->ddc->dev.kobj, "ddc"); return 0; }
@@ -294,6 +298,10 @@ void drm_sysfs_connector_remove(struct drm_connector *connector) { if (!connector->kdev) return; + + if (connector->ddc) + sysfs_remove_link(&connector->kdev->kobj, "ddc"); + DRM_DEBUG("removing "%s" from sysfs\n", connector->name);
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 97ea41dc6..d8f4e66fb 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -40,6 +40,7 @@ struct drm_property; struct drm_property_blob; struct drm_printer; struct edid; +struct i2c_adapter;
enum drm_connector_force { DRM_FORCE_UNSPECIFIED, @@ -998,6 +999,16 @@ struct drm_connector { * [0]: progressive, [1]: interlaced */ int audio_latency[2]; + + /** + * @ddc: associated ddc adapter. + * A connector usually has its associated ddc adapter. If a driver uses + * this field, then an appropriate symbolic link is created in connector + * sysfs directory to make it easy for the user to tell which i2c + * adapter is for a particular display. + */ + struct i2c_adapter *ddc; + /** * @null_edid_counter: track sinks that give us all zeros for the EDID. * Needed to workaround some HW bugs where we get all 0s
From: gouhao gouhao@uniontech.com
mainline inclusion from mainline-v5.14.0-rc7 commit 100163df420305b78153e6f5ec10c90d755acee3 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I469VQ CVE: NA
----------------------------------------
Allow passing ddc adapter pointer to the init function. Even if drm_connector_init() sometime in the future decides to e.g. memset() all connector fields to zeros, the newly added function ensures that at its completion the ddc member of connector is correctly set.
Signed-off-by: Andrzej Pietrasiewicz andrzej.p@collabora.com Acked-by: Thomas Zimmermann tzimmermann@suse.de Reviewed-by: Emil Velikov emil.velikov@collabora.com Reviewed-by: Sam Ravnborg sam@ravnborg.org Signed-off-by: Neil Armstrong narmstrong@baylibre.com Link: https://patchwork.freedesktop.org/patch/msgid/3915224ae895240fd0973cf7f06b9d...
Signed-off-by: gouhao gouhao@uniontech.com --- drivers/gpu/drm/drm_connector.c | 35 +++++++++++++++++++++++++++++++++ include/drm/drm_connector.h | 7 +++++++ 2 files changed, 42 insertions(+)
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 6011d769d..ed49d0e93 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -290,6 +290,41 @@ out_put: } EXPORT_SYMBOL(drm_connector_init);
+/** + * drm_connector_init_with_ddc - Init a preallocated connector + * @dev: DRM device + * @connector: the connector to init + * @funcs: callbacks for this connector + * @connector_type: user visible type of the connector + * @ddc: pointer to the associated ddc adapter + * + * Initialises a preallocated connector. Connectors should be + * subclassed as part of driver connector objects. + * + * Ensures that the ddc field of the connector is correctly set. + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_connector_init_with_ddc(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc) +{ + int ret; + + ret = drm_connector_init(dev, connector, funcs, connector_type); + if (ret) + return ret; + + /* provide ddc symlink in sysfs */ + connector->ddc = ddc; + + return ret; +} +EXPORT_SYMBOL(drm_connector_init_with_ddc); + /** * drm_connector_attach_encoder - attach a connector to an encoder * @connector: connector to attach diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index d8f4e66fb..db9b04888 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1006,6 +1006,8 @@ struct drm_connector { * this field, then an appropriate symbolic link is created in connector * sysfs directory to make it easy for the user to tell which i2c * adapter is for a particular display. + * + * The field should be set by calling drm_connector_init_with_ddc(). */ struct i2c_adapter *ddc;
@@ -1094,6 +1096,11 @@ int drm_connector_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type); +int drm_connector_init_with_ddc(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc); int drm_connector_register(struct drm_connector *connector); void drm_connector_unregister(struct drm_connector *connector); int drm_connector_attach_encoder(struct drm_connector *connector,
From: gouhao gouhao@uniontech.com
mainline inclusion from mainline-v5.14.0-rc7 commit 4eb4d99dfe3018d86f4529112aa7082f43b6996a category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I469VQ CVE: NA
-----------------------------
Adding driver implementation to support i2c driver algorithms for bit-shift adapters, so hibmc will using the interface provided by drm to read edid.
Signed-off-by: Tian Tao tiantao6@hisilicon.com Reviewed-by: Thomas Zimmermann tzimmermann@suse.de Link: https://patchwork.freedesktop.org/patch/msgid/1600778670-60370-2-git-send-em...
Signed-off-by: gouhao gouhao@uniontech.com --- drivers/gpu/drm/hisilicon/hibmc/Makefile | 3 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 26 +++++ .../gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c | 99 +++++++++++++++++++ 3 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile index 3df726696..71c248f4c 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/Makefile +++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile @@ -1,3 +1,4 @@ -hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_drm_fbdev.o hibmc_ttm.o +hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o \ + hibmc_drm_fbdev.o hibmc_ttm.o hibmc_drm_i2c.o
obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc-drm.o diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index 4395dc667..884ca5b47 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -19,12 +19,18 @@ #ifndef HIBMC_DRM_DRV_H #define HIBMC_DRM_DRV_H
+#include <linux/gpio/consumer.h> +#include <linux/i2c-algo-bit.h> +#include <linux/i2c.h> + +#include <drm/drm_edid.h> #include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> #include <drm/ttm/ttm_bo_driver.h>
+ struct hibmc_framebuffer { struct drm_framebuffer fb; struct drm_gem_object *obj; @@ -36,6 +42,13 @@ struct hibmc_fbdev { int size; };
+struct hibmc_connector { + struct drm_connector base; + + struct i2c_adapter adapter; + struct i2c_algo_bit_data bit_data; +}; + struct hibmc_drm_private { /* hw */ void __iomem *mmio; @@ -46,6 +59,8 @@ struct hibmc_drm_private {
/* drm */ struct drm_device *dev; + struct drm_encoder encoder; + struct hibmc_connector connector; bool mode_config_initialized; struct drm_atomic_state *suspend_state;
@@ -60,6 +75,16 @@ struct hibmc_drm_private { bool mm_inited; };
+static inline struct hibmc_connector *to_hibmc_connector(struct drm_connector *connector) +{ + return container_of(connector, struct hibmc_connector, base); +} + +static inline struct hibmc_drm_private *to_hibmc_drm_private(struct drm_device *dev) +{ + return dev->dev_private; +} + #define to_hibmc_framebuffer(x) container_of(x, struct hibmc_framebuffer, fb)
struct hibmc_bo { @@ -110,6 +135,7 @@ int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, int hibmc_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev, u32 handle, u64 *offset); int hibmc_mmap(struct file *filp, struct vm_area_struct *vma); +int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_connector *connector);
extern const struct drm_mode_config_funcs hibmc_mode_funcs;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c new file mode 100644 index 000000000..86d712090 --- /dev/null +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Hisilicon Hibmc SoC drm driver + * + * Based on the bochs drm driver. + * + * Copyright (c) 2016 Huawei Limited. + * + * Author: + * Tian Tao tiantao6@hisilicon.com + */ + +#include <linux/delay.h> +#include <linux/pci.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_probe_helper.h> + +#include "hibmc_drm_drv.h" + +#define GPIO_DATA 0x0802A0 +#define GPIO_DATA_DIRECTION 0x0802A4 + +#define I2C_SCL_MASK BIT(0) +#define I2C_SDA_MASK BIT(1) + +static void hibmc_set_i2c_signal(void *data, u32 mask, int value) +{ + struct hibmc_connector *hibmc_connector = data; + struct hibmc_drm_private *priv = to_hibmc_drm_private(hibmc_connector->base.dev); + u32 tmp_dir = readl(priv->mmio + GPIO_DATA_DIRECTION); + + if (value) { + tmp_dir &= ~mask; + writel(tmp_dir, priv->mmio + GPIO_DATA_DIRECTION); + } else { + u32 tmp_data = readl(priv->mmio + GPIO_DATA); + + tmp_data &= ~mask; + writel(tmp_data, priv->mmio + GPIO_DATA); + + tmp_dir |= mask; + writel(tmp_dir, priv->mmio + GPIO_DATA_DIRECTION); + } +} + +static int hibmc_get_i2c_signal(void *data, u32 mask) +{ + struct hibmc_connector *hibmc_connector = data; + struct hibmc_drm_private *priv = to_hibmc_drm_private(hibmc_connector->base.dev); + u32 tmp_dir = readl(priv->mmio + GPIO_DATA_DIRECTION); + + if ((tmp_dir & mask) != mask) { + tmp_dir &= ~mask; + writel(tmp_dir, priv->mmio + GPIO_DATA_DIRECTION); + } + + return (readl(priv->mmio + GPIO_DATA) & mask) ? 1 : 0; +} + +static void hibmc_ddc_setsda(void *data, int state) +{ + hibmc_set_i2c_signal(data, I2C_SDA_MASK, state); +} + +static void hibmc_ddc_setscl(void *data, int state) +{ + hibmc_set_i2c_signal(data, I2C_SCL_MASK, state); +} + +static int hibmc_ddc_getsda(void *data) +{ + return hibmc_get_i2c_signal(data, I2C_SDA_MASK); +} + +static int hibmc_ddc_getscl(void *data) +{ + return hibmc_get_i2c_signal(data, I2C_SCL_MASK); +} + +int hibmc_ddc_create(struct drm_device *drm_dev, + struct hibmc_connector *connector) +{ + connector->adapter.owner = THIS_MODULE; + connector->adapter.class = I2C_CLASS_DDC; + snprintf(connector->adapter.name, I2C_NAME_SIZE, "HIS i2c bit bus"); + connector->adapter.dev.parent = &drm_dev->pdev->dev; + i2c_set_adapdata(&connector->adapter, connector); + connector->adapter.algo_data = &connector->bit_data; + + connector->bit_data.udelay = 20; + connector->bit_data.timeout = usecs_to_jiffies(2000); + connector->bit_data.data = connector; + connector->bit_data.setsda = hibmc_ddc_setsda; + connector->bit_data.setscl = hibmc_ddc_setscl; + connector->bit_data.getsda = hibmc_ddc_getsda; + connector->bit_data.getscl = hibmc_ddc_getscl; + + return i2c_bit_add_bus(&connector->adapter); +}
From: gouhao gouhao@uniontech.com
mainline inclusion from mainline-v5.14.0-rc7 commit a0d078d06e516184e2f575f3803935697b5e3ac6 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I469VQ CVE: NA
The modification of hibmc_vdac_init in the original patch cannot be incorporated. In this patch, the hibmc_vdac_init is backport from the mainline code.
---------------------------------------
Use drm_get_edid to get the resolution, if that fails, set it to a fixed resolution. Rewrite the desrtoy callback function to release resources.
Signed-off-by: Tian Tao tiantao6@hisilicon.com Reviewed-by: Thomas Zimmermann tzimmermann@suse.de Link: https://patchwork.freedesktop.org/patch/msgid/1600778670-60370-3-git-send-em...
Signed-off-by: gouhao gouhao@uniontech.com --- .../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 55 ++++++++++++++----- 1 file changed, 41 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index 90319a902..762e3404e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -59,11 +59,23 @@ static int hibmc_valid_mode(int w, int h) static int hibmc_connector_get_modes(struct drm_connector *connector) { int count; + void *edid; + struct hibmc_connector *hibmc_connector = to_hibmc_connector(connector); + + edid = drm_get_edid(connector, &hibmc_connector->adapter); + if (edid) { + drm_connector_update_edid_property(connector, edid); + count = drm_add_edid_modes(connector, edid); + if (count) + goto out; + }
drm_connector_update_edid_property(connector, NULL); count = drm_add_modes_noedid(connector, 1920, 1200); drm_set_preferred_mode(connector, 1024, 768);
+out: + kfree(edid); return count; }
@@ -86,6 +98,14 @@ hibmc_connector_best_encoder(struct drm_connector *connector) return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); }
+static void hibmc_connector_destroy(struct drm_connector *connector) +{ + struct hibmc_connector *hibmc_connector = to_hibmc_connector(connector); + + i2c_del_adapter(&hibmc_connector->adapter); + drm_connector_cleanup(connector); +} + static const struct drm_connector_helper_funcs hibmc_connector_helper_funcs = { .get_modes = hibmc_connector_get_modes, @@ -95,7 +115,7 @@ static const struct drm_connector_helper_funcs
static const struct drm_connector_funcs hibmc_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = drm_connector_cleanup, + .destroy = hibmc_connector_destroy, .reset = drm_atomic_helper_connector_reset, .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, @@ -155,21 +175,16 @@ static const struct drm_encoder_funcs hibmc_encoder_funcs = { int hibmc_vdac_init(struct hibmc_drm_private *priv) { struct drm_device *dev = priv->dev; - struct drm_encoder *encoder; - struct drm_connector *connector; + struct hibmc_connector *hibmc_connector = &priv->connector; + struct drm_encoder *encoder = &priv->encoder; + struct drm_connector *connector = &hibmc_connector->base; int ret;
- connector = hibmc_connector_init(priv); - if (IS_ERR(connector)) { - DRM_ERROR("failed to create connector: %ld\n", - PTR_ERR(connector)); - return PTR_ERR(connector); - } - - encoder = devm_kzalloc(dev->dev, sizeof(*encoder), GFP_KERNEL); - if (!encoder) { - DRM_ERROR("failed to alloc memory when init encoder\n"); - return -ENOMEM; + + ret = hibmc_ddc_create(dev, hibmc_connector); + if (ret) { + DRM_ERROR("failed to create ddc: %d\n", ret); + return ret; }
encoder->possible_crtcs = 0x1; @@ -181,6 +196,18 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv) }
drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs); + + ret = drm_connector_init_with_ddc(dev, connector, + &hibmc_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &hibmc_connector->adapter); + if (ret) { + DRM_ERROR("failed to init connector: %d\n", ret); + return ret; + } + + drm_connector_helper_add(connector, &hibmc_connector_helper_funcs); + drm_connector_attach_encoder(connector, encoder);
return 0;