Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b309bd37 authored by Adam Jackson's avatar Adam Jackson Committed by Dave Airlie
Browse files

drm/edid: Generate modes from extra_modes for range descriptors

parent b61b2140
Loading
Loading
Loading
Loading
+73 −0
Original line number Diff line number Diff line
@@ -1037,11 +1037,61 @@ drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
	return modes;
}

static int
drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
			struct detailed_timing *timing)
{
	int i, modes = 0;
	struct drm_display_mode *newmode;
	struct drm_device *dev = connector->dev;

	for (i = 0; i < num_extra_modes; i++) {
		const struct minimode *m = &extra_modes[i];
		newmode = drm_gtf_mode(dev, m->w, m->h, m->r, 0, 0);

		if (!mode_in_range(newmode, edid, timing)) {
			drm_mode_destroy(dev, newmode);
			continue;
		}

		drm_mode_probed_add(connector, newmode);
		modes++;
	}

	return modes;
}

static int
drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
			struct detailed_timing *timing)
{
	int i, modes = 0;
	struct drm_display_mode *newmode;
	struct drm_device *dev = connector->dev;
	bool rb = drm_monitor_supports_rb(edid);

	for (i = 0; i < num_extra_modes; i++) {
		const struct minimode *m = &extra_modes[i];
		newmode = drm_cvt_mode(dev, m->w, m->h, m->r, rb, 0, 0);

		if (!mode_in_range(newmode, edid, timing)) {
			drm_mode_destroy(dev, newmode);
			continue;
		}

		drm_mode_probed_add(connector, newmode);
		modes++;
	}

	return modes;
}

static void
do_inferred_modes(struct detailed_timing *timing, void *c)
{
	struct detailed_mode_closure *closure = c;
	struct detailed_non_pixel *data = &timing->data.other_data;
	struct detailed_data_monitor_range *range = &data->data.range;

	if (data->type != EDID_DETAIL_MONITOR_RANGE)
		return;
@@ -1049,6 +1099,29 @@ do_inferred_modes(struct detailed_timing *timing, void *c)
	closure->modes += drm_dmt_modes_for_range(closure->connector,
						  closure->edid,
						  timing);
	
	if (!version_greater(closure->edid, 1, 1))
		return; /* GTF not defined yet */

	switch (range->flags) {
	case 0x02: /* secondary gtf, XXX could do more */
	case 0x00: /* default gtf */
		closure->modes += drm_gtf_modes_for_range(closure->connector,
							  closure->edid,
							  timing);
		break;
	case 0x04: /* cvt, only in 1.4+ */
		if (!version_greater(closure->edid, 1, 3))
			break;

		closure->modes += drm_cvt_modes_for_range(closure->connector,
							  closure->edid,
							  timing);
		break;
	case 0x01: /* just the ranges, no formula */
	default:
		break;
	}
}

static int