diff options
Diffstat (limited to 'drivers/gpu/drm/drm_modes.c')
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 82 |
1 files changed, 53 insertions, 29 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 893f52ee4926..e72f855fc495 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -373,8 +373,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hact_duration_ns < params->hact_ns.min || hact_duration_ns > params->hact_ns.max)) { - DRM_ERROR("Invalid horizontal active area duration: %uns (min: %u, max %u)\n", - hact_duration_ns, params->hact_ns.min, params->hact_ns.max); + drm_err(dev, "Invalid horizontal active area duration: %uns (min: %u, max %u)\n", + hact_duration_ns, params->hact_ns.min, params->hact_ns.max); return -EINVAL; } @@ -385,8 +385,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hblk_duration_ns < params->hblk_ns.min || hblk_duration_ns > params->hblk_ns.max)) { - DRM_ERROR("Invalid horizontal blanking duration: %uns (min: %u, max %u)\n", - hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max); + drm_err(dev, "Invalid horizontal blanking duration: %uns (min: %u, max %u)\n", + hblk_duration_ns, params->hblk_ns.min, params->hblk_ns.max); return -EINVAL; } @@ -397,8 +397,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hslen_duration_ns < params->hslen_ns.min || hslen_duration_ns > params->hslen_ns.max)) { - DRM_ERROR("Invalid horizontal sync duration: %uns (min: %u, max %u)\n", - hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max); + drm_err(dev, "Invalid horizontal sync duration: %uns (min: %u, max %u)\n", + hslen_duration_ns, params->hslen_ns.min, params->hslen_ns.max); return -EINVAL; } @@ -409,7 +409,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (porches_duration_ns > (params->hfp_ns.max + params->hbp_ns.max) || porches_duration_ns < (params->hfp_ns.min + params->hbp_ns.min))) { - DRM_ERROR("Invalid horizontal porches duration: %uns\n", porches_duration_ns); + drm_err(dev, "Invalid horizontal porches duration: %uns\n", + porches_duration_ns); return -EINVAL; } @@ -431,8 +432,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hfp_duration_ns < params->hfp_ns.min || hfp_duration_ns > params->hfp_ns.max)) { - DRM_ERROR("Invalid horizontal front porch duration: %uns (min: %u, max %u)\n", - hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max); + drm_err(dev, "Invalid horizontal front porch duration: %uns (min: %u, max %u)\n", + hfp_duration_ns, params->hfp_ns.min, params->hfp_ns.max); return -EINVAL; } @@ -443,8 +444,8 @@ static int fill_analog_mode(struct drm_device *dev, if (!bt601 && (hbp_duration_ns < params->hbp_ns.min || hbp_duration_ns > params->hbp_ns.max)) { - DRM_ERROR("Invalid horizontal back porch duration: %uns (min: %u, max %u)\n", - hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max); + drm_err(dev, "Invalid horizontal back porch duration: %uns (min: %u, max %u)\n", + hbp_duration_ns, params->hbp_ns.min, params->hbp_ns.max); return -EINVAL; } @@ -495,8 +496,8 @@ static int fill_analog_mode(struct drm_device *dev, vtotal = vactive + vfp + vslen + vbp; if (params->num_lines != vtotal) { - DRM_ERROR("Invalid vertical total: %upx (expected %upx)\n", - vtotal, params->num_lines); + drm_err(dev, "Invalid vertical total: %upx (expected %upx)\n", + vtotal, params->num_lines); return -EINVAL; } @@ -530,14 +531,14 @@ static int fill_analog_mode(struct drm_device *dev, * @interlace: whether to compute an interlaced mode * * This function creates a struct drm_display_mode instance suited for - * an analog TV output, for one of the usual analog TV mode. + * an analog TV output, for one of the usual analog TV modes. Where + * this is DRM_MODE_TV_MODE_MONOCHROME, a 625-line mode will be created. * * Note that @hdisplay is larger than the usual constraints for the PAL * and NTSC timings, and we'll choose to ignore most timings constraints * to reach those resolutions. * * Returns: - * * A pointer to the mode, allocated with drm_mode_create(). Returns NULL * on error. */ @@ -568,6 +569,8 @@ struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev, case DRM_MODE_TV_MODE_PAL_N: fallthrough; case DRM_MODE_TV_MODE_SECAM: + fallthrough; + case DRM_MODE_TV_MODE_MONOCHROME: analog = DRM_MODE_ANALOG_PAL; break; @@ -1200,9 +1203,8 @@ int of_get_drm_display_mode(struct device_node *np, if (bus_flags) drm_bus_flags_from_videomode(&vm, bus_flags); - pr_debug("%pOF: got %dx%d display mode\n", - np, vm.hactive, vm.vactive); - drm_mode_debug_printmodeline(dmode); + pr_debug("%pOF: got %dx%d display mode: " DRM_MODE_FMT "\n", + np, vm.hactive, vm.vactive, DRM_MODE_ARG(dmode)); return 0; } @@ -1250,7 +1252,7 @@ int of_get_drm_panel_display_mode(struct device_node *np, dmode->width_mm = width_mm; dmode->height_mm = height_mm; - drm_mode_debug_printmodeline(dmode); + pr_debug(DRM_MODE_FMT "\n", DRM_MODE_ARG(dmode)); return 0; } @@ -1280,19 +1282,15 @@ EXPORT_SYMBOL(drm_mode_set_name); * @mode: mode * * Returns: - * @modes's vrefresh rate in Hz, rounded to the nearest integer. Calculates the - * value first if it is not yet set. + * @modes's vrefresh rate in Hz, rounded to the nearest integer. */ int drm_mode_vrefresh(const struct drm_display_mode *mode) { - unsigned int num, den; + unsigned int num = 1, den = 1; if (mode->htotal == 0 || mode->vtotal == 0) return 0; - num = mode->clock; - den = mode->htotal * mode->vtotal; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) num *= 2; if (mode->flags & DRM_MODE_FLAG_DBLSCAN) @@ -1300,6 +1298,12 @@ int drm_mode_vrefresh(const struct drm_display_mode *mode) if (mode->vscan > 1) den *= mode->vscan; + if (check_mul_overflow(mode->clock, num, &num)) + return 0; + + if (check_mul_overflow(mode->htotal * mode->vtotal, den, &den)) + return 0; + return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den); } EXPORT_SYMBOL(drm_mode_vrefresh); @@ -1812,10 +1816,8 @@ void drm_mode_prune_invalid(struct drm_device *dev, DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); } if (verbose) { - drm_mode_debug_printmodeline(mode); - DRM_DEBUG_KMS("Not using %s mode: %s\n", - mode->name, - drm_get_mode_status_name(mode->status)); + drm_dbg_kms(dev, "Rejected mode: " DRM_MODE_FMT " (%s)\n", + DRM_MODE_ARG(mode), drm_get_mode_status_name(mode->status)); } drm_mode_destroy(dev, mode); } @@ -2752,3 +2754,25 @@ bool drm_mode_is_420(const struct drm_display_info *display, drm_mode_is_420_also(display, mode); } EXPORT_SYMBOL(drm_mode_is_420); + +/** + * drm_set_preferred_mode - Sets the preferred mode of a connector + * @connector: connector whose mode list should be processed + * @hpref: horizontal resolution of preferred mode + * @vpref: vertical resolution of preferred mode + * + * Marks a mode as preferred if it matches the resolution specified by @hpref + * and @vpref. + */ +void drm_set_preferred_mode(struct drm_connector *connector, + int hpref, int vpref) +{ + struct drm_display_mode *mode; + + list_for_each_entry(mode, &connector->probed_modes, head) { + if (mode->hdisplay == hpref && + mode->vdisplay == vpref) + mode->type |= DRM_MODE_TYPE_PREFERRED; + } +} +EXPORT_SYMBOL(drm_set_preferred_mode); |