diff options
Diffstat (limited to 'drivers/gpu/drm/tilcdc')
| -rw-r--r-- | drivers/gpu/drm/tilcdc/Kconfig | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/tilcdc/Makefile | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 57 | ||||
| -rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_panel.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c | 270 | ||||
| -rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_slave_compat.dts | 72 | ||||
| -rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_slave_compat.h | 25 | ||||
| -rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 4 | 
9 files changed, 51 insertions, 399 deletions
| diff --git a/drivers/gpu/drm/tilcdc/Kconfig b/drivers/gpu/drm/tilcdc/Kconfig index 28fed7e206d0..81ac82455ce4 100644 --- a/drivers/gpu/drm/tilcdc/Kconfig +++ b/drivers/gpu/drm/tilcdc/Kconfig @@ -12,14 +12,3 @@ config DRM_TILCDC  	  controller, for example AM33xx in beagle-bone, DA8xx, or  	  OMAP-L1xx.  This driver replaces the FB_DA8XX fbdev driver. -config DRM_TILCDC_SLAVE_COMPAT -	bool "Support device tree blobs using TI LCDC Slave binding" -	depends on DRM_TILCDC -	default y -	select OF_RESOLVE -	select OF_OVERLAY -	help -	  Choose this option if you need a kernel that is compatible -	  with device tree blobs using the obsolete "ti,tilcdc,slave" -	  binding. If you find "ti,tilcdc,slave"-string from your DTB, -	  you probably need this. Otherwise you do not. diff --git a/drivers/gpu/drm/tilcdc/Makefile b/drivers/gpu/drm/tilcdc/Makefile index 55ebd516728f..87f9480e43b0 100644 --- a/drivers/gpu/drm/tilcdc/Makefile +++ b/drivers/gpu/drm/tilcdc/Makefile @@ -1,10 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0  ifeq (, $(findstring -W,$(EXTRA_CFLAGS)))  	ccflags-y += -Werror  endif -obj-$(CONFIG_DRM_TILCDC_SLAVE_COMPAT) += tilcdc_slave_compat.o \ -					 tilcdc_slave_compat.dtb.o -  tilcdc-y := \  	tilcdc_plane.o \  	tilcdc_crtc.o \ diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 406fe4544b83..6ef4d1a1e3a9 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -24,6 +24,7 @@  #include <linux/completion.h>  #include <linux/dma-mapping.h>  #include <linux/of_graph.h> +#include <linux/math64.h>  #include "tilcdc_drv.h"  #include "tilcdc_regs.h" @@ -48,6 +49,7 @@ struct tilcdc_crtc {  	unsigned int lcd_fck_rate;  	ktime_t last_vblank; +	unsigned int hvtotal_us;  	struct drm_framebuffer *curr_fb;  	struct drm_framebuffer *next_fb; @@ -75,7 +77,7 @@ static void unref_worker(struct drm_flip_work *work, void *val)  	struct drm_device *dev = tilcdc_crtc->base.dev;  	mutex_lock(&dev->mode_config.mutex); -	drm_framebuffer_unreference(val); +	drm_framebuffer_put(val);  	mutex_unlock(&dev->mode_config.mutex);  } @@ -292,6 +294,12 @@ static void tilcdc_crtc_set_clk(struct drm_crtc *crtc)  				LCDC_V2_CORE_CLK_EN);  } +uint tilcdc_mode_hvtotal(const struct drm_display_mode *mode) +{ +	return (uint) div_u64(1000llu * mode->htotal * mode->vtotal, +			      mode->clock); +} +  static void tilcdc_crtc_set_mode(struct drm_crtc *crtc)  {  	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); @@ -456,9 +464,12 @@ static void tilcdc_crtc_set_mode(struct drm_crtc *crtc)  	set_scanout(crtc, fb); -	drm_framebuffer_reference(fb); +	drm_framebuffer_get(fb);  	crtc->hwmode = crtc->state->adjusted_mode; + +	tilcdc_crtc->hvtotal_us = +		tilcdc_mode_hvtotal(&crtc->hwmode);  }  static void tilcdc_crtc_enable(struct drm_crtc *crtc) @@ -467,7 +478,6 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc)  	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);  	unsigned long flags; -	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));  	mutex_lock(&tilcdc_crtc->enable_lock);  	if (tilcdc_crtc->enabled || tilcdc_crtc->shutdown) {  		mutex_unlock(&tilcdc_crtc->enable_lock); @@ -564,7 +574,6 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown)  static void tilcdc_crtc_disable(struct drm_crtc *crtc)  { -	WARN_ON(!drm_modeset_is_locked(&crtc->mutex));  	tilcdc_crtc_off(crtc, false);  } @@ -608,9 +617,7 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc)  	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);  	struct tilcdc_drm_private *priv = crtc->dev->dev_private; -	drm_modeset_lock(&crtc->mutex, NULL); -	tilcdc_crtc_disable(crtc); -	drm_modeset_unlock(&crtc->mutex); +	tilcdc_crtc_shutdown(crtc);  	flush_workqueue(priv->wq); @@ -626,14 +633,12 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,  	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);  	struct drm_device *dev = crtc->dev; -	WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); -  	if (tilcdc_crtc->event) {  		dev_err(dev->dev, "already pending page flip!\n");  		return -EBUSY;  	} -	drm_framebuffer_reference(fb); +	drm_framebuffer_get(fb);  	crtc->primary->fb = fb;  	tilcdc_crtc->event = event; @@ -648,7 +653,7 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,  		spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);  		next_vblank = ktime_add_us(tilcdc_crtc->last_vblank, -					   1000000 / crtc->hwmode.vrefresh); +					   tilcdc_crtc->hvtotal_us);  		tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get()));  		if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US) @@ -728,11 +733,39 @@ static void tilcdc_crtc_disable_vblank(struct drm_crtc *crtc)  {  } +static void tilcdc_crtc_reset(struct drm_crtc *crtc) +{ +	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); +	struct drm_device *dev = crtc->dev; +	int ret; + +	drm_atomic_helper_crtc_reset(crtc); + +	/* Turn the raster off if it for some reason is on. */ +	pm_runtime_get_sync(dev->dev); +	if (tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & LCDC_RASTER_ENABLE) { +		/* Enable DMA Frame Done Interrupt */ +		tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_FRAME_DONE); +		tilcdc_clear_irqstatus(dev, 0xffffffff); + +		tilcdc_crtc->frame_done = false; +		tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); + +		ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, +					 tilcdc_crtc->frame_done, +					 msecs_to_jiffies(500)); +		if (ret == 0) +			dev_err(dev->dev, "%s: timeout waiting for framedone\n", +				__func__); +	} +	pm_runtime_put_sync(dev->dev); +} +  static const struct drm_crtc_funcs tilcdc_crtc_funcs = {  	.destroy        = tilcdc_crtc_destroy,  	.set_config     = drm_atomic_helper_set_config,  	.page_flip      = drm_atomic_helper_page_flip, -	.reset		= drm_atomic_helper_crtc_reset, +	.reset		= tilcdc_crtc_reset,  	.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,  	.enable_vblank	= tilcdc_crtc_enable_vblank, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index b0d70f943cec..72ce063aa0d8 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -23,6 +23,7 @@  #include <drm/drm_atomic.h>  #include <drm/drm_atomic_helper.h>  #include <drm/drm_fb_helper.h> +#include <drm/drm_gem_framebuffer_helper.h>  #include "tilcdc_drv.h"  #include "tilcdc_regs.h" @@ -65,7 +66,7 @@ static struct of_device_id tilcdc_of_match[];  static struct drm_framebuffer *tilcdc_fb_create(struct drm_device *dev,  		struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd)  { -	return drm_fb_cma_create(dev, file_priv, mode_cmd); +	return drm_gem_fb_create(dev, file_priv, mode_cmd);  }  static void tilcdc_fb_output_poll_changed(struct drm_device *dev) @@ -225,7 +226,7 @@ static void tilcdc_fini(struct drm_device *dev)  	pm_runtime_disable(dev->dev); -	drm_dev_unref(dev); +	drm_dev_put(dev);  }  static int tilcdc_init(struct drm_driver *ddrv, struct device *dev) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 1813a3623ce6..8eebb5f826a6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -418,7 +418,7 @@ static int panel_remove(struct platform_device *pdev)  	return 0;  } -static struct of_device_id panel_of_match[] = { +static const struct of_device_id panel_of_match[] = {  		{ .compatible = "ti,tilcdc,panel", },  		{ },  }; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c deleted file mode 100644 index 623a9140493c..000000000000 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2015 Texas Instruments - * Author: Jyri Sarha <[email protected]> - * - * 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. - * - */ - -/* - * To support the old "ti,tilcdc,slave" binding the binding has to be - * transformed to the new external encoder binding. - */ - -#include <linux/kernel.h> -#include <linux/of.h> -#include <linux/of_graph.h> -#include <linux/of_fdt.h> -#include <linux/slab.h> -#include <linux/list.h> - -#include "tilcdc_slave_compat.h" - -struct kfree_table { -	int total; -	int num; -	void **table; -}; - -static int __init kfree_table_init(struct kfree_table *kft) -{ -	kft->total = 32; -	kft->num = 0; -	kft->table = kmalloc(kft->total * sizeof(*kft->table), -			     GFP_KERNEL); -	if (!kft->table) -		return -ENOMEM; - -	return 0; -} - -static int __init kfree_table_add(struct kfree_table *kft, void *p) -{ -	if (kft->num == kft->total) { -		void **old = kft->table; - -		kft->total *= 2; -		kft->table = krealloc(old, kft->total * sizeof(*kft->table), -				      GFP_KERNEL); -		if (!kft->table) { -			kft->table = old; -			kfree(p); -			return -ENOMEM; -		} -	} -	kft->table[kft->num++] = p; -	return 0; -} - -static void __init kfree_table_free(struct kfree_table *kft) -{ -	int i; - -	for (i = 0; i < kft->num; i++) -		kfree(kft->table[i]); - -	kfree(kft->table); -} - -static -struct property * __init tilcdc_prop_dup(const struct property *prop, -					 struct kfree_table *kft) -{ -	struct property *nprop; - -	nprop = kzalloc(sizeof(*nprop), GFP_KERNEL); -	if (!nprop || kfree_table_add(kft, nprop)) -		return NULL; - -	nprop->name = kstrdup(prop->name, GFP_KERNEL); -	if (!nprop->name || kfree_table_add(kft, nprop->name)) -		return NULL; - -	nprop->value = kmemdup(prop->value, prop->length, GFP_KERNEL); -	if (!nprop->value || kfree_table_add(kft, nprop->value)) -		return NULL; - -	nprop->length = prop->length; - -	return nprop; -} - -static void __init tilcdc_copy_props(struct device_node *from, -				     struct device_node *to, -				     const char * const props[], -				     struct kfree_table *kft) -{ -	struct property *prop; -	int i; - -	for (i = 0; props[i]; i++) { -		prop = of_find_property(from, props[i], NULL); -		if (!prop) -			continue; - -		prop = tilcdc_prop_dup(prop, kft); -		if (!prop) -			continue; - -		prop->next = to->properties; -		to->properties = prop; -	} -} - -static int __init tilcdc_prop_str_update(struct property *prop, -					  const char *str, -					  struct kfree_table *kft) -{ -	prop->value = kstrdup(str, GFP_KERNEL); -	if (kfree_table_add(kft, prop->value) || !prop->value) -		return -ENOMEM; -	prop->length = strlen(str)+1; -	return 0; -} - -static void __init tilcdc_node_disable(struct device_node *node) -{ -	struct property *prop; - -	prop = kzalloc(sizeof(*prop), GFP_KERNEL); -	if (!prop) -		return; - -	prop->name = "status"; -	prop->value = "disabled"; -	prop->length = strlen((char *)prop->value)+1; - -	of_update_property(node, prop); -} - -static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) -{ -	const int size = __dtb_tilcdc_slave_compat_end - -		__dtb_tilcdc_slave_compat_begin; -	static void *overlay_data; -	struct device_node *overlay; -	int ret; - -	if (!size) { -		pr_warn("%s: No overlay data\n", __func__); -		return NULL; -	} - -	overlay_data = kmemdup(__dtb_tilcdc_slave_compat_begin, -			       size, GFP_KERNEL); -	if (!overlay_data || kfree_table_add(kft, overlay_data)) -		return NULL; - -	of_fdt_unflatten_tree(overlay_data, NULL, &overlay); -	if (!overlay) { -		pr_warn("%s: Unfattening overlay tree failed\n", __func__); -		return NULL; -	} - -	of_node_set_flag(overlay, OF_DETACHED); -	ret = of_resolve_phandles(overlay); -	if (ret) { -		pr_err("%s: Failed to resolve phandles: %d\n", __func__, ret); -		return NULL; -	} - -	return overlay; -} - -static const struct of_device_id tilcdc_slave_of_match[] __initconst = { -	{ .compatible = "ti,tilcdc,slave", }, -	{}, -}; - -static const struct of_device_id tilcdc_of_match[] __initconst = { -	{ .compatible = "ti,am33xx-tilcdc", }, -	{}, -}; - -static const struct of_device_id tilcdc_tda998x_of_match[] __initconst = { -	{ .compatible = "nxp,tda998x", }, -	{}, -}; - -static const char * const tilcdc_slave_props[] __initconst = { -	"pinctrl-names", -	"pinctrl-0", -	"pinctrl-1", -	NULL -}; - -static void __init tilcdc_convert_slave_node(void) -{ -	struct device_node *slave = NULL, *lcdc = NULL; -	struct device_node *i2c = NULL, *fragment = NULL; -	struct device_node *overlay, *encoder; -	struct property *prop; -	/* For all memory needed for the overlay tree. This memory can -	   be freed after the overlay has been applied. */ -	struct kfree_table kft; -	int ret; - -	if (kfree_table_init(&kft)) -		return; - -	lcdc = of_find_matching_node(NULL, tilcdc_of_match); -	slave = of_find_matching_node(NULL, tilcdc_slave_of_match); - -	if (!slave || !of_device_is_available(lcdc)) -		goto out; - -	i2c = of_parse_phandle(slave, "i2c", 0); -	if (!i2c) { -		pr_err("%s: Can't find i2c node trough phandle\n", __func__); -		goto out; -	} - -	overlay = tilcdc_get_overlay(&kft); -	if (!overlay) -		goto out; - -	encoder = of_find_matching_node(overlay, tilcdc_tda998x_of_match); -	if (!encoder) { -		pr_err("%s: Failed to find tda998x node\n", __func__); -		goto out; -	} - -	tilcdc_copy_props(slave, encoder, tilcdc_slave_props, &kft); - -	for_each_child_of_node(overlay, fragment) { -		prop = of_find_property(fragment, "target-path", NULL); -		if (!prop) -			continue; -		if (!strncmp("i2c", (char *)prop->value, prop->length)) -			if (tilcdc_prop_str_update(prop, i2c->full_name, &kft)) -				goto out; -		if (!strncmp("lcdc", (char *)prop->value, prop->length)) -			if (tilcdc_prop_str_update(prop, lcdc->full_name, &kft)) -				goto out; -	} - -	tilcdc_node_disable(slave); - -	ret = of_overlay_create(overlay); -	if (ret) -		pr_err("%s: Creating overlay failed: %d\n", __func__, ret); -	else -		pr_info("%s: ti,tilcdc,slave node successfully converted\n", -			__func__); -out: -	kfree_table_free(&kft); -	of_node_put(i2c); -	of_node_put(slave); -	of_node_put(lcdc); -	of_node_put(fragment); -} - -static int __init tilcdc_slave_compat_init(void) -{ -	tilcdc_convert_slave_node(); -	return 0; -} - -subsys_initcall(tilcdc_slave_compat_init); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.dts b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.dts deleted file mode 100644 index 693f8b0aea2d..000000000000 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.dts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * DTS overlay for converting ti,tilcdc,slave binding to new binding. - * - * Copyright (C) 2015 Texas Instruments Inc. - * Author: Jyri Sarha <[email protected]> - * - * 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. - */ - -/* - * target-path property values are simple tags that are replaced with - * correct values in tildcdc_slave_compat.c. Some properties are also - * copied over from the ti,tilcdc,slave node. - */ - -/dts-v1/; -/ { -	fragment@0 { -		target-path = "i2c"; -		__overlay__ { -			#address-cells = <1>; -			#size-cells = <0>; -			tda19988 { -				compatible = "nxp,tda998x"; -				reg = <0x70>; -				status = "okay"; - -				port { -					hdmi_0: endpoint@0 { -						remote-endpoint = <&lcd_0>; -					}; -				}; -			}; -		}; -	}; - -	fragment@1 { -		target-path = "lcdc"; -		__overlay__ { -			port { -				lcd_0: endpoint@0 { -					remote-endpoint = <&hdmi_0>; -				}; -			}; -		}; -	}; - -	__local_fixups__ { -		fragment@0 { -			__overlay__ { -				tda19988 { -					port { -						endpoint@0 { -							remote-endpoint	= <0>; -						}; -					}; -				}; -			}; -		}; -		fragment@1 { -			__overlay__ { -				port { -					endpoint@0 { -						remote-endpoint	= <0>; -					}; -				}; -			}; -		}; -	}; -}; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.h b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.h deleted file mode 100644 index 403d35d87d0b..000000000000 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2015 Texas Instruments - * Author: Jyri Sarha <[email protected]> - * - * 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. - * - * You should have received a copy of the GNU General Public License along with - * this program.  If not, see <http://www.gnu.org/licenses/>. - */ -/* This header declares the symbols defined in tilcdc_slave_compat.dts */ - -#ifndef __TILCDC_SLAVE_COMPAT_H__ -#define __TILCDC_SLAVE_COMPAT_H__ - -extern uint8_t __dtb_tilcdc_slave_compat_begin[]; -extern uint8_t __dtb_tilcdc_slave_compat_end[]; - -#endif /* __TILCDC_SLAVE_COMPAT_H__ */ diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 1e2dfb1b1d6b..7e3643462a08 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -289,8 +289,6 @@ static const struct tilcdc_module_ops tfp410_module_ops = {   * Device:   */ -static struct of_device_id tfp410_of_match[]; -  static int tfp410_probe(struct platform_device *pdev)  {  	struct device_node *node = pdev->dev.of_node; @@ -375,7 +373,7 @@ static int tfp410_remove(struct platform_device *pdev)  	return 0;  } -static struct of_device_id tfp410_of_match[] = { +static const struct of_device_id tfp410_of_match[] = {  		{ .compatible = "ti,tilcdc,tfp410", },  		{ },  }; |