diff --git a/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender-tianma.dts b/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender-tianma.dts index f14e214921b46b..16fee469707de9 100644 --- a/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender-tianma.dts +++ b/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender-tianma.dts @@ -16,23 +16,30 @@ status = "okay"; /* Novatek NT36672A touchscreen */ - touchscreen@62 { - compatible = "novatek,nt36525"; - reg = <0x62>; - vdd-supply = <&vreg_l11a_1p8>; - interrupt-parent = <&tlmm>; - interrupts = <67 IRQ_TYPE_EDGE_RISING>; + touchscreen@1 { + compatible = "novatek,nt36672a-ts"; + reg = <0x1>; + iovcc-supply = <&vreg_l11a_1p8>; + interrupts-extended = <&tlmm 67 IRQ_TYPE_EDGE_RISING>; + + // Fixme, I think the driver can only handle default state pinctrl-names = "default", "sleep"; pinctrl-0 = <&ts_pins_active>; pinctrl-1 = <&ts_int_sleep &ts_rst_sleep>; - reset-gpios = <&tlmm 66 GPIO_ACTIVE_HIGH>; + reset-gpios = <&tlmm 66 GPIO_ACTIVE_LOW>; + + // Maybe they are not used by the driver touchscreen-size-x = <1080>; touchscreen-size-y = <2340>; }; }; &panel { - compatible = "tianma,nt36672a-xiaomi-lavender-simple"; + compatible = "tianma,nt36672a-xiaomi-lavender"; + vddio-supply = <&vreg_l11a_1p8>; + // There is no lcdb driver yet + // vsn-supply = <>; + // vsp-supply = <> }; &tlmm { diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index c627e42a7ce704..870bf8d471ee9c 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -74,8 +74,9 @@ EXPORT_SYMBOL(drm_panel_init); * drm_panel_add - add a panel to the global registry * @panel: panel to add * - * Add a panel to the global registry so that it can be looked up by display - * drivers. + * Add a panel to the global registry so that it can be looked + * up by display drivers. The panel to be added must have been + * allocated by devm_drm_panel_alloc(). */ void drm_panel_add(struct drm_panel *panel) { @@ -355,6 +356,93 @@ struct drm_panel *of_drm_find_panel(const struct device_node *np) } EXPORT_SYMBOL(of_drm_find_panel); +static void __drm_panel_free(struct kref *kref) +{ + struct drm_panel *panel = container_of(kref, struct drm_panel, refcount); + + kfree(panel->container); +} + +/** + * drm_panel_get - Acquire a panel reference + * @panel: DRM panel + * + * This function increments the panel's refcount. + * Returns: + * Pointer to @panel + */ +struct drm_panel *drm_panel_get(struct drm_panel *panel) +{ + if (!panel) + return panel; + + kref_get(&panel->refcount); + + return panel; +} +EXPORT_SYMBOL(drm_panel_get); + +/** + * drm_panel_put - Release a panel reference + * @panel: DRM panel + * + * This function decrements the panel's reference count and frees the + * object if the reference count drops to zero. + */ +void drm_panel_put(struct drm_panel *panel) +{ + if (panel) + kref_put(&panel->refcount, __drm_panel_free); +} +EXPORT_SYMBOL(drm_panel_put); + +/** + * drm_panel_put_void - wrapper to drm_panel_put() taking a void pointer + * + * @data: pointer to @struct drm_panel, cast to a void pointer + * + * Wrapper of drm_panel_put() to be used when a function taking a void + * pointer is needed, for example as a devm action. + */ +static void drm_panel_put_void(void *data) +{ + struct drm_panel *panel = (struct drm_panel *)data; + + drm_panel_put(panel); +} + +void *__devm_drm_panel_alloc(struct device *dev, size_t size, size_t offset, + const struct drm_panel_funcs *funcs, + int connector_type) +{ + void *container; + struct drm_panel *panel; + int err; + + if (!funcs) { + dev_warn(dev, "Missing funcs pointer\n"); + return ERR_PTR(-EINVAL); + } + + container = kzalloc(size, GFP_KERNEL); + if (!container) + return ERR_PTR(-ENOMEM); + + panel = container + offset; + panel->container = container; + panel->funcs = funcs; + kref_init(&panel->refcount); + + err = devm_add_action_or_reset(dev, drm_panel_put_void, panel); + if (err) + return ERR_PTR(err); + + drm_panel_init(panel, dev, funcs, connector_type); + + return container; +} +EXPORT_SYMBOL(__devm_drm_panel_alloc); + /** * of_drm_get_panel_orientation - look up the orientation of the panel through * the "rotation" binding from a device tree node diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index adb7e572519698..0091cc7b5c49ec 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -515,6 +515,16 @@ config DRM_PANEL_NOVATEK_NT36672A around the Novatek NT36672A display controller, such as some Tianma panels used in a few Xiaomi Poco F1 mobile phones. +config DRM_PANEL_NOVATEK_NT36672A_TIANMAPLUS + tristate "Novatek NT36672A DSI panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for the panels built + around the Novatek NT36672A display controller, such as some + Tianma panels used in a few Xiaomi Poco F1 mobile phones. + config DRM_PANEL_NOVATEK_NT36672E tristate "Novatek NT36672E DSI panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index ff9ac5dac6dc40..2435a1a5de15c0 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35560) += panel-novatek-nt35560.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35950) += panel-novatek-nt35950.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36523) += panel-novatek-nt36523.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A) += panel-novatek-nt36672a.o +obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672A_TIANMAPLUS) += panel-nt36672a-tianmaplus.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672E) += panel-novatek-nt36672e.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672_TIANMA_JASMINE) += panel-novatek-nt36672-tianma-jasmine.o obj-$(CONFIG_DRM_PANEL_NOVATEK_NT36672_TXD) += panel-novatek-nt36672-txd.o diff --git a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c index c2abd20e0734bd..dfc6a4e19a7044 100644 --- a/drivers/gpu/drm/panel/panel-novatek-nt36672a.c +++ b/drivers/gpu/drm/panel/panel-novatek-nt36672a.c @@ -28,10 +28,6 @@ #include