brintos

brintos / linux-shallow public Read only

0
0
Text · 5.5 KiB · 1a37470 Raw
221 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/**************************************************************************3 * Copyright (c) 2007-2011, Intel Corporation.4 * All Rights Reserved.5 *6 **************************************************************************/7 8#include <drm/drm_framebuffer.h>9#include <drm/drm_gem_framebuffer_helper.h>10#include <drm/drm_modeset_helper.h>11 12#include "framebuffer.h"13#include "psb_drv.h"14 15static const struct drm_framebuffer_funcs psb_fb_funcs = {16	.destroy = drm_gem_fb_destroy,17	.create_handle = drm_gem_fb_create_handle,18};19 20/**21 *	psb_framebuffer_init	-	initialize a framebuffer22 *	@dev: our DRM device23 *	@fb: framebuffer to set up24 *	@mode_cmd: mode description25 *	@obj: backing object26 *27 *	Configure and fill in the boilerplate for our frame buffer. Return28 *	0 on success or an error code if we fail.29 */30static int psb_framebuffer_init(struct drm_device *dev,31					struct drm_framebuffer *fb,32					const struct drm_mode_fb_cmd2 *mode_cmd,33					struct drm_gem_object *obj)34{35	const struct drm_format_info *info;36	int ret;37 38	/*39	 * Reject unknown formats, YUV formats, and formats with more than40	 * 4 bytes per pixel.41	 */42	info = drm_get_format_info(dev, mode_cmd);43	if (!info || !info->depth || info->cpp[0] > 4)44		return -EINVAL;45 46	if (mode_cmd->pitches[0] & 63)47		return -EINVAL;48 49	drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);50	fb->obj[0] = obj;51	ret = drm_framebuffer_init(dev, fb, &psb_fb_funcs);52	if (ret) {53		dev_err(dev->dev, "framebuffer init failed: %d\n", ret);54		return ret;55	}56	return 0;57}58 59/**60 *	psb_framebuffer_create	-	create a framebuffer backed by gt61 *	@dev: our DRM device62 *	@mode_cmd: the description of the requested mode63 *	@obj: the backing object64 *65 *	Create a framebuffer object backed by the gt, and fill in the66 *	boilerplate required67 *68 *	TODO: review object references69 */70struct drm_framebuffer *psb_framebuffer_create(struct drm_device *dev,71					       const struct drm_mode_fb_cmd2 *mode_cmd,72					       struct drm_gem_object *obj)73{74	struct drm_framebuffer *fb;75	int ret;76 77	fb = kzalloc(sizeof(*fb), GFP_KERNEL);78	if (!fb)79		return ERR_PTR(-ENOMEM);80 81	ret = psb_framebuffer_init(dev, fb, mode_cmd, obj);82	if (ret) {83		kfree(fb);84		return ERR_PTR(ret);85	}86	return fb;87}88 89/**90 *	psb_user_framebuffer_create	-	create framebuffer91 *	@dev: our DRM device92 *	@filp: client file93 *	@cmd: mode request94 *95 *	Create a new framebuffer backed by a userspace GEM object96 */97static struct drm_framebuffer *psb_user_framebuffer_create98			(struct drm_device *dev, struct drm_file *filp,99			 const struct drm_mode_fb_cmd2 *cmd)100{101	struct drm_gem_object *obj;102	struct drm_framebuffer *fb;103 104	/*105	 *	Find the GEM object and thus the gtt range object that is106	 *	to back this space107	 */108	obj = drm_gem_object_lookup(filp, cmd->handles[0]);109	if (obj == NULL)110		return ERR_PTR(-ENOENT);111 112	/* Let the core code do all the work */113	fb = psb_framebuffer_create(dev, cmd, obj);114	if (IS_ERR(fb))115		drm_gem_object_put(obj);116 117	return fb;118}119 120static const struct drm_mode_config_funcs psb_mode_funcs = {121	.fb_create = psb_user_framebuffer_create,122};123 124static void psb_setup_outputs(struct drm_device *dev)125{126	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);127	struct drm_connector_list_iter conn_iter;128	struct drm_connector *connector;129 130	drm_mode_create_scaling_mode_property(dev);131 132	/* It is ok for this to fail - we just don't get backlight control */133	if (!dev_priv->backlight_property)134		dev_priv->backlight_property = drm_property_create_range(dev, 0,135							"backlight", 0, 100);136	dev_priv->ops->output_init(dev);137 138	drm_connector_list_iter_begin(dev, &conn_iter);139	drm_for_each_connector_iter(connector, &conn_iter) {140		struct gma_encoder *gma_encoder = gma_attached_encoder(connector);141		struct drm_encoder *encoder = &gma_encoder->base;142		int crtc_mask = 0, clone_mask = 0;143 144		/* valid crtcs */145		switch (gma_encoder->type) {146		case INTEL_OUTPUT_ANALOG:147			crtc_mask = (1 << 0);148			clone_mask = (1 << INTEL_OUTPUT_ANALOG);149			break;150		case INTEL_OUTPUT_SDVO:151			crtc_mask = dev_priv->ops->sdvo_mask;152			clone_mask = 0;153			break;154		case INTEL_OUTPUT_LVDS:155			crtc_mask = dev_priv->ops->lvds_mask;156			clone_mask = 0;157			break;158		case INTEL_OUTPUT_MIPI:159			crtc_mask = (1 << 0);160			clone_mask = 0;161			break;162		case INTEL_OUTPUT_MIPI2:163			crtc_mask = (1 << 2);164			clone_mask = 0;165			break;166		case INTEL_OUTPUT_HDMI:167			crtc_mask = dev_priv->ops->hdmi_mask;168			clone_mask = (1 << INTEL_OUTPUT_HDMI);169			break;170		case INTEL_OUTPUT_DISPLAYPORT:171			crtc_mask = (1 << 0) | (1 << 1);172			clone_mask = 0;173			break;174		case INTEL_OUTPUT_EDP:175			crtc_mask = (1 << 1);176			clone_mask = 0;177		}178		encoder->possible_crtcs = crtc_mask;179		encoder->possible_clones =180		    gma_connector_clones(dev, clone_mask);181	}182	drm_connector_list_iter_end(&conn_iter);183}184 185void psb_modeset_init(struct drm_device *dev)186{187	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);188	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;189	int i;190 191	if (drmm_mode_config_init(dev))192		return;193 194	dev->mode_config.min_width = 0;195	dev->mode_config.min_height = 0;196 197	dev->mode_config.funcs = &psb_mode_funcs;198 199	/* num pipes is 2 for PSB but 1 for Mrst */200	for (i = 0; i < dev_priv->num_pipe; i++)201		psb_intel_crtc_init(dev, i, mode_dev);202 203	dev->mode_config.max_width = 4096;204	dev->mode_config.max_height = 4096;205 206	psb_setup_outputs(dev);207 208	if (dev_priv->ops->errata)209	        dev_priv->ops->errata(dev);210 211        dev_priv->modeset = true;212}213 214void psb_modeset_cleanup(struct drm_device *dev)215{216	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);217	if (dev_priv->modeset) {218		drm_kms_helper_poll_fini(dev);219	}220}221