コード例 #1
0
ファイル: drm_edid.c プロジェクト: tellapart/ubuntu-precise
/**
 * drm_edid_is_valid - sanity check EDID data
 * @edid: EDID data
 *
 * Sanity-check an entire EDID record (including extensions)
 */
bool drm_edid_is_valid(struct edid *edid)
{
	int i;
	u8 *raw = (u8 *)edid;

	if (!edid)
		return false;

	for (i = 0; i <= edid->extensions; i++)
		if (!drm_edid_block_valid(raw + i * EDID_LENGTH))
			return false;

	return true;
}
コード例 #2
0
static int edid_load(struct drm_connector *connector, char *name,
		     char *connector_name)
{
	const struct firmware *fw;
	struct platform_device *pdev;
	u8 *fwdata = NULL, *edid;
	int fwsize, expected;
	int builtin = 0, err = 0;
	int i, valid_extensions = 0;

	pdev = platform_device_register_simple(connector_name, -1, NULL, 0);
	if (IS_ERR(pdev)) {
		DRM_ERROR("Failed to register EDID firmware platform device "
		    "for connector \"%s\"\n", connector_name);
		err = -EINVAL;
		goto out;
	}

	err = request_firmware(&fw, name, &pdev->dev);
	platform_device_unregister(pdev);

	if (err) {
		i = 0;
		while (i < GENERIC_EDIDS && strcmp(name, generic_edid_name[i]))
			i++;
		if (i < GENERIC_EDIDS) {
			err = 0;
			builtin = 1;
			fwdata = generic_edid[i];
			fwsize = sizeof(generic_edid[i]);
		}
	}

	if (err) {
		DRM_ERROR("Requesting EDID firmware \"%s\" failed (err=%d)\n",
		    name, err);
		goto out;
	}

	if (fwdata == NULL) {
		fwdata = (u8 *) fw->data;
		fwsize = fw->size;
	}

	expected = (fwdata[0x7e] + 1) * EDID_LENGTH;
	if (expected != fwsize) {
		DRM_ERROR("Size of EDID firmware \"%s\" is invalid "
		    "(expected %d, got %d)\n", name, expected, (int) fwsize);
		err = -EINVAL;
		goto relfw_out;
	}

	edid = kmalloc(fwsize, GFP_KERNEL);
	if (edid == NULL) {
		err = -ENOMEM;
		goto relfw_out;
	}
	memcpy(edid, fwdata, fwsize);

	if (!drm_edid_block_valid(edid)) {
		DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
		    name);
		kfree(edid);
		err = -EINVAL;
		goto relfw_out;
	}

	for (i = 1; i <= edid[0x7e]; i++) {
		if (i != valid_extensions + 1)
			memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
			    edid + i * EDID_LENGTH, EDID_LENGTH);
		if (drm_edid_block_valid(edid + i * EDID_LENGTH))
			valid_extensions++;
	}

	if (valid_extensions != edid[0x7e]) {
		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
		DRM_INFO("Found %d valid extensions instead of %d in EDID data "
		    "\"%s\" for connector \"%s\"\n", valid_extensions,
		    edid[0x7e], name, connector_name);
		edid[0x7e] = valid_extensions;
		edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,
		    GFP_KERNEL);
		if (edid == NULL) {
			err = -ENOMEM;
			goto relfw_out;
		}
	}

	connector->display_info.raw_edid = edid;
	DRM_INFO("Got %s EDID base block and %d extension%s from "
	    "\"%s\" for connector \"%s\"\n", builtin ? "built-in" :
	    "external", valid_extensions, valid_extensions == 1 ? "" : "s",
	    name, connector_name);

relfw_out:
	release_firmware(fw);

out:
	return err;
}
コード例 #3
0
static u8 *edid_load(struct drm_connector *connector, const char *name,
			const char *connector_name)
{
	const struct firmware *fw = NULL;
	const u8 *fwdata;
	u8 *edid;
	int fwsize, builtin;
	int i, valid_extensions = 0;
	bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & DRM_UT_KMS);

	builtin = 0;
	for (i = 0; i < GENERIC_EDIDS; i++) {
		if (strcmp(name, generic_edid_name[i]) == 0) {
			fwdata = generic_edid[i];
			fwsize = sizeof(generic_edid[i]);
			builtin = 1;
			break;
		}
	}
	if (!builtin) {
		struct platform_device *pdev;
		int err;

		pdev = platform_device_register_simple(connector_name, -1, NULL, 0);
		if (IS_ERR(pdev)) {
			DRM_ERROR("Failed to register EDID firmware platform device "
				  "for connector \"%s\"\n", connector_name);
			return ERR_CAST(pdev);
		}

		err = request_firmware(&fw, name, &pdev->dev);
		platform_device_unregister(pdev);
		if (err) {
			DRM_ERROR("Requesting EDID firmware \"%s\" failed (err=%d)\n",
				  name, err);
			return ERR_PTR(err);
		}

		fwdata = fw->data;
		fwsize = fw->size;
	}

	if (edid_size(fwdata, fwsize) != fwsize) {
		DRM_ERROR("Size of EDID firmware \"%s\" is invalid "
			  "(expected %d, got %d\n", name,
			  edid_size(fwdata, fwsize), (int)fwsize);
		edid = ERR_PTR(-EINVAL);
		goto out;
	}

	edid = kmemdup(fwdata, fwsize, GFP_KERNEL);
	if (edid == NULL) {
		edid = ERR_PTR(-ENOMEM);
		goto out;
	}

	if (!drm_edid_block_valid(edid, 0, print_bad_edid)) {
		connector->bad_edid_counter++;
		DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
		    name);
		kfree(edid);
		edid = ERR_PTR(-EINVAL);
		goto out;
	}

	for (i = 1; i <= edid[0x7e]; i++) {
		if (i != valid_extensions + 1)
			memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
			    edid + i * EDID_LENGTH, EDID_LENGTH);
		if (drm_edid_block_valid(edid + i * EDID_LENGTH, i, print_bad_edid))
			valid_extensions++;
	}

	if (valid_extensions != edid[0x7e]) {
		u8 *new_edid;

		edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
		DRM_INFO("Found %d valid extensions instead of %d in EDID data "
		    "\"%s\" for connector \"%s\"\n", valid_extensions,
		    edid[0x7e], name, connector_name);
		edid[0x7e] = valid_extensions;

		new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,
				    GFP_KERNEL);
		if (new_edid)
			edid = new_edid;
	}

	DRM_INFO("Got %s EDID base block and %d extension%s from "
	    "\"%s\" for connector \"%s\"\n", builtin ? "built-in" :
	    "external", valid_extensions, valid_extensions == 1 ? "" : "s",
	    name, connector_name);

out:
	if (fw)
		release_firmware(fw);
	return edid;
}