diff options
Diffstat (limited to 'drivers/gpu/drm/tiny')
| -rw-r--r-- | drivers/gpu/drm/tiny/ofdrm.c | 27 | ||||
| -rw-r--r-- | drivers/gpu/drm/tiny/simpledrm.c | 138 | 
2 files changed, 93 insertions, 72 deletions
| diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c index 33eefeba437c..6e349ca42485 100644 --- a/drivers/gpu/drm/tiny/ofdrm.c +++ b/drivers/gpu/drm/tiny/ofdrm.c @@ -754,24 +754,6 @@ static void ofdrm_crtc_state_destroy(struct ofdrm_crtc_state *ofdrm_crtc_state)  	kfree(ofdrm_crtc_state);  } -/* - * Support all formats of OF display and maybe more; in order - * of preference. The display's update function will do any - * conversion necessary. - * - * TODO: Add blit helpers for remaining formats and uncomment - *       constants. - */ -static const uint32_t ofdrm_primary_plane_formats[] = { -	DRM_FORMAT_XRGB8888, -	DRM_FORMAT_RGB565, -	//DRM_FORMAT_XRGB1555, -	//DRM_FORMAT_C8, -	/* Big-endian formats below */ -	DRM_FORMAT_BGRX8888, -	DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN, -}; -  static const uint64_t ofdrm_primary_plane_format_modifiers[] = {  	DRM_FORMAT_MOD_LINEAR,  	DRM_FORMAT_MOD_INVALID @@ -1290,8 +1272,6 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,  	/* Primary plane */  	nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, -					    ofdrm_primary_plane_formats, -					    ARRAY_SIZE(ofdrm_primary_plane_formats),  					    odev->formats, ARRAY_SIZE(odev->formats));  	primary_plane = &odev->primary_plane; @@ -1372,6 +1352,7 @@ static int ofdrm_probe(struct platform_device *pdev)  {  	struct ofdrm_device *odev;  	struct drm_device *dev; +	unsigned int color_mode;  	int ret;  	odev = ofdrm_device_create(&ofdrm_driver, pdev); @@ -1383,7 +1364,11 @@ static int ofdrm_probe(struct platform_device *pdev)  	if (ret)  		return ret; -	drm_fbdev_generic_setup(dev, drm_format_info_bpp(odev->format, 0)); +	color_mode = drm_format_info_bpp(odev->format, 0); +	if (color_mode == 16) +		color_mode = odev->format->depth; // can be 15 or 16 + +	drm_fbdev_generic_setup(dev, color_mode);  	return 0;  } diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 30e928d627e8..2acc0eb32489 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -3,6 +3,7 @@  #include <linux/clk.h>  #include <linux/of_clk.h>  #include <linux/minmax.h> +#include <linux/of_address.h>  #include <linux/platform_data/simplefb.h>  #include <linux/platform_device.h>  #include <linux/regulator/consumer.h> @@ -184,6 +185,31 @@ simplefb_get_format_of(struct drm_device *dev, struct device_node *of_node)  	return simplefb_get_validated_format(dev, format);  } +static struct resource * +simplefb_get_memory_of(struct drm_device *dev, struct device_node *of_node) +{ +	struct device_node *np; +	struct resource *res; +	int err; + +	np = of_parse_phandle(of_node, "memory-region", 0); +	if (!np) +		return NULL; + +	res = devm_kzalloc(dev->dev, sizeof(*res), GFP_KERNEL); +	if (!res) +		return ERR_PTR(-ENOMEM); + +	err = of_address_to_resource(np, 0, res); +	if (err) +		return ERR_PTR(err); + +	if (of_get_property(of_node, "reg", NULL)) +		drm_warn(dev, "preferring \"memory-region\" over \"reg\" property\n"); + +	return res; +} +  /*   * Simple Framebuffer device   */ @@ -208,7 +234,7 @@ struct simpledrm_device {  	unsigned int pitch;  	/* memory management */ -	void __iomem *screen_base; +	struct iosys_map screen_base;  	/* modesetting */  	uint32_t formats[8]; @@ -446,25 +472,6 @@ static int simpledrm_device_init_regulators(struct simpledrm_device *sdev)   * Modesetting   */ -/* - * Support all formats of simplefb and maybe more; in order - * of preference. The display's update function will do any - * conversion necessary. - * - * TODO: Add blit helpers for remaining formats and uncomment - *       constants. - */ -static const uint32_t simpledrm_primary_plane_formats[] = { -	DRM_FORMAT_XRGB8888, -	DRM_FORMAT_ARGB8888, -	DRM_FORMAT_RGB565, -	//DRM_FORMAT_XRGB1555, -	//DRM_FORMAT_ARGB1555, -	DRM_FORMAT_RGB888, -	DRM_FORMAT_XRGB2101010, -	DRM_FORMAT_ARGB2101010, -}; -  static const uint64_t simpledrm_primary_plane_format_modifiers[] = {  	DRM_FORMAT_MOD_LINEAR,  	DRM_FORMAT_MOD_INVALID @@ -492,15 +499,15 @@ static void simpledrm_primary_plane_helper_atomic_update(struct drm_plane *plane  	drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);  	drm_atomic_for_each_plane_damage(&iter, &damage) { -		struct iosys_map dst = IOSYS_MAP_INIT_VADDR(sdev->screen_base);  		struct drm_rect dst_clip = plane_state->dst; +		struct iosys_map dst = sdev->screen_base;  		if (!drm_rect_intersect(&dst_clip, &damage))  			continue;  		iosys_map_incr(&dst, drm_fb_clip_offset(sdev->pitch, sdev->format, &dst_clip)); -		drm_fb_blit(&dst, &sdev->pitch, sdev->format->format, shadow_plane_state->data, fb, -			    &damage); +		drm_fb_blit(&dst, &sdev->pitch, sdev->format->format, shadow_plane_state->data, +			    fb, &damage);  	}  	drm_dev_exit(idx); @@ -519,7 +526,7 @@ static void simpledrm_primary_plane_helper_atomic_disable(struct drm_plane *plan  		return;  	/* Clear screen to black if disabled */ -	memset_io(sdev->screen_base, 0, sdev->pitch * sdev->mode.vdisplay); +	iosys_map_memset(&sdev->screen_base, 0, 0, sdev->pitch * sdev->mode.vdisplay);  	drm_dev_exit(idx);  } @@ -623,8 +630,7 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,  	struct drm_device *dev;  	int width, height, stride;  	const struct drm_format_info *format; -	struct resource *res, *mem; -	void __iomem *screen_base; +	struct resource *res, *mem = NULL;  	struct drm_plane *primary_plane;  	struct drm_crtc *crtc;  	struct drm_encoder *encoder; @@ -676,6 +682,9 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,  		format = simplefb_get_format_of(dev, of_node);  		if (IS_ERR(format))  			return ERR_CAST(format); +		mem = simplefb_get_memory_of(dev, of_node); +		if (IS_ERR(mem)) +			return ERR_CAST(mem);  	} else {  		drm_err(dev, "no simplefb configuration found\n");  		return ERR_PTR(-ENODEV); @@ -698,31 +707,55 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,  	 * Memory management  	 */ -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) -		return ERR_PTR(-EINVAL); +	if (mem) { +		void *screen_base; -	ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res)); -	if (ret) { -		drm_err(dev, "could not acquire memory range %pr: error %d\n", res, ret); -		return ERR_PTR(ret); -	} +		ret = devm_aperture_acquire_from_firmware(dev, mem->start, resource_size(mem)); +		if (ret) { +			drm_err(dev, "could not acquire memory range %pr: %d\n", mem, ret); +			return ERR_PTR(ret); +		} -	mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res), drv->name); -	if (!mem) { -		/* -		 * We cannot make this fatal. Sometimes this comes from magic -		 * spaces our resource handlers simply don't know about. Use -		 * the I/O-memory resource as-is and try to map that instead. -		 */ -		drm_warn(dev, "could not acquire memory region %pr\n", res); -		mem = res; -	} +		drm_dbg(dev, "using system memory framebuffer at %pr\n", mem); -	screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem)); -	if (!screen_base) -		return ERR_PTR(-ENOMEM); -	sdev->screen_base = screen_base; +		screen_base = devm_memremap(dev->dev, mem->start, resource_size(mem), MEMREMAP_WC); +		if (!screen_base) +			return ERR_PTR(-ENOMEM); + +		iosys_map_set_vaddr(&sdev->screen_base, screen_base); +	} else { +		void __iomem *screen_base; + +		res = platform_get_resource(pdev, IORESOURCE_MEM, 0); +		if (!res) +			return ERR_PTR(-EINVAL); + +		ret = devm_aperture_acquire_from_firmware(dev, res->start, resource_size(res)); +		if (ret) { +			drm_err(dev, "could not acquire memory range %pr: %d\n", &res, ret); +			return ERR_PTR(ret); +		} + +		drm_dbg(dev, "using I/O memory framebuffer at %pr\n", res); + +		mem = devm_request_mem_region(&pdev->dev, res->start, resource_size(res), +					      drv->name); +		if (!mem) { +			/* +			 * We cannot make this fatal. Sometimes this comes from magic +			 * spaces our resource handlers simply don't know about. Use +			 * the I/O-memory resource as-is and try to map that instead. +			 */ +			drm_warn(dev, "could not acquire memory region %pr\n", res); +			mem = res; +		} + +		screen_base = devm_ioremap_wc(&pdev->dev, mem->start, resource_size(mem)); +		if (!screen_base) +			return ERR_PTR(-ENOMEM); + +		iosys_map_set_vaddr_iomem(&sdev->screen_base, screen_base); +	}  	/*  	 * Modesetting @@ -745,8 +778,6 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv,  	/* Primary plane */  	nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, -					    simpledrm_primary_plane_formats, -					    ARRAY_SIZE(simpledrm_primary_plane_formats),  					    sdev->formats, ARRAY_SIZE(sdev->formats));  	primary_plane = &sdev->primary_plane; @@ -823,6 +854,7 @@ static int simpledrm_probe(struct platform_device *pdev)  {  	struct simpledrm_device *sdev;  	struct drm_device *dev; +	unsigned int color_mode;  	int ret;  	sdev = simpledrm_device_create(&simpledrm_driver, pdev); @@ -834,7 +866,11 @@ static int simpledrm_probe(struct platform_device *pdev)  	if (ret)  		return ret; -	drm_fbdev_generic_setup(dev, drm_format_info_bpp(sdev->format, 0)); +	color_mode = drm_format_info_bpp(sdev->format, 0); +	if (color_mode == 16) +		color_mode = sdev->format->depth; // can be 15 or 16 + +	drm_fbdev_generic_setup(dev, color_mode);  	return 0;  } | 
