drm/edid: Generate modes from extra_modes for range descriptors
Signed-off-by: Adam Jackson <ajax@redhat.com> Tested-by: Takashi Iwai <tiwai@suse.de> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
b61b2140fe
commit
b309bd37a1
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue