/*
*/
/*
*
* Copyright © 1997-2003 by The XFree86 Project, Inc.
* Copyright © 2007 Dave Airlie
* Copyright (c) 2007-2008, 2013, Intel Corporation
* Jesse Barnes <jesse.barnes@intel.com>
* Copyright 2005-2006 Luc Verhaegen
* Copyright (c) 2001, Andy Ritger aritger@nvidia.com
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the copyright holder(s)
* and author(s) shall not be used in advertising or otherwise to promote
* the sale, use or other dealings in this Software without prior written
* authorization from the copyright holder(s) and author(s).
*/
#include "drmP.h"
#include "drm.h"
#include "drm_crtc.h"
#include "drm_linux_list.h"
/**
* drm_mode_debug_printmodeline - debug print a mode
* @dev: DRM device
* @mode: mode to print
*
* LOCKING:
* None.
*
* Describe @mode using DRM_DEBUG.
*/
{
DRM_DEBUG_KMS("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d "
"0x%x 0x%x\n",
}
/**
* drm_cvt_mode -create a modeline based on CVT algorithm
* @dev: DRM device
* @hdisplay: hdisplay size
* @vdisplay: vdisplay size
* @vrefresh : vrefresh rate
* @reduced : Whether the GTF calculation is simplified
* @interlaced:Whether the interlace is supported
*
* LOCKING:
* none.
*
* return the modeline based on CVT algorithm
*
* This function is called to generate the modeline based on CVT algorithm
* according to the hdisplay, vdisplay, vrefresh.
* It is based from the VESA(TM) Coordinated Video Timing Generator by
* Graham Loveridge April 9, 2003 available at
*
* What I have done is to translate it by using integer calculation.
*/
{
/* 2) character cell horizontal granularity (pixels) - default 8 */
/* 3) Minimum vertical porch (lines) - default 3 */
/* 4) Minimum number of vertical back porch lines - default 6 */
/* Pixel Clock step (kHz) */
int interlace;
/* allocate the drm_display_mode structure. If failure, we will
* return directly
*/
if (!drm_mode)
return NULL;
/* the CVT default refresh rate is 60Hz */
if (!vrefresh)
vrefresh = 60;
/* the required field fresh rate */
if (interlaced)
else
/* horizontal pixels */
/* determine the left&right borders */
hmargin = 0;
if (margins) {
}
/* find the total active pixels */
/* find the number of lines per field */
if (interlaced)
else
/* find the top & bottom borders */
vmargin = 0;
if (margins)
/* Interlaced */
if (interlaced)
interlace = 1;
else
interlace = 0;
/* Determine VSync Width from aspect ratio */
vsync = 4;
vsync = 5;
vsync = 6;
vsync = 7;
vsync = 7;
else /* custom */
vsync = 10;
if (!reduced) {
/* simplify the GTF calculation */
/* 4) Minimum time of vertical sync + back porch interval (µs)
* default 550.0
*/
/* 3) Nominal HSync width (% of line period) - default 8 */
unsigned int hblank_percentage;
/* LINTED */
/* estimated the horizontal period */
/* 9. Find number of lines in sync + backporch */
else
/* 10. Find number of lines in back porch */
/* 5) Definition of Horizontal blanking time limitation */
/* Gradient (%/kHz) - default 600 */
/* Offset (%) - default 40 */
/* Blanking time scaling factor - default 128 */
/* Scaling factor weighting - default 20 */
/* 12. Find ideal blanking duty cycle from formula */
hperiod / 1000;
/* 13. Blanking time */
/* 14. find the total pixes per line */
/* fill the Vsync values */
} else {
/* Reduced blanking */
/* Minimum vertical blanking interval time (µs)- default 460 */
/* Fixed number of clocks for horizontal sync */
/* Fixed number of clocks for horizontal blanking */
/* Fixed number of lines for vertical front porch - default 3*/
int vbilines;
/* 8. Estimate Horizontal period. */
/* 9. Find number of lines in vertical blanking */
/* 10. Check if vertical blanking is sufficient */
/* 11. Find total number of lines in vertical field */
/* 12. Find total number of pixels in a line */
/* Fill in HSync values */
/* Fill in VSync values */
}
/* 15/13. Find pixel clock frequency (kHz for xf86) */
/* 18/16. Find actual vertical frame frequency */
/* ignore - just set the mode flag for interlaced */
if (interlaced) {
}
/* Fill the mode line name */
if (reduced)
else
return drm_mode;
}
/**
* drm_gtf_mode - create the modeline based on GTF algorithm
*
* @dev :drm device
* @hdisplay :hdisplay size
* @vdisplay :vdisplay size
* @vrefresh :vrefresh rate.
* @interlaced :whether the interlace is supported
* @margins :whether the margin is supported
* @GTF_[MCKJ] :extended GTF formula parameters
*
* LOCKING.
* none.
*
* return the modeline based on GTF algorithm
*
* GTF feature blocks specify C and J in multiples of 0.5, so we pass them
* in here multiplied by two. For a C of 40, pass in 80.
*/
struct drm_display_mode *
/* 2) character cell horizontal granularity (pixels) - default 8 */
/* 3) Minimum vertical porch (lines) - default 3 */
/* width of vsync in lines */
/* width of hsync as % of total line */
/* min time of vsync + back porch (microsec) */
/* C' and M' are part of the Blanking Duty Cycle computation */
int interlace;
unsigned int hfreq_est;
/* LINTED */
/* LINTED */
/* LINTED */
if (!drm_mode)
return NULL;
/* 1. In order to give correct results, the number of horizontal
* pixels requested is first processed to ensure that it is divisible
* by the character size, by rounding it to the nearest character
* cell boundary:
*/
/* 2. If interlace is requested, the number of vertical lines assumed
* by the calculation must be halved, as the computation calculates
* the number of vertical lines per field.
*/
if (interlaced)
else
/* 3. Find the frame rate required: */
if (interlaced)
else
/* 4. Find number of lines in Top margin: */
top_margin = 0;
if (margins)
1000;
/* 5. Find number of lines in bottom margin: */
/* 6. If interlace is required, then set variable interlace: */
if (interlaced)
interlace = 1;
else
interlace = 0;
/* 7. Estimate the Horizontal frequency */
{
2 + interlace;
}
/* 8. Find the number of lines in V sync + back porch */
/* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */
/* 9. Find the number of lines in V back porch alone: */
/* 10. Find the total number of lines in Vertical field period: */
/* 11. Estimate the Vertical field frequency: */
/* 12. Find the actual horizontal period: */
/* 13. Find the actual Vertical field frequency: */
/* 14. Find the Vertical frame frequency: */
if (interlaced)
else
/* 15. Find number of pixels in left margin: */
if (margins)
1000;
else
left_margin = 0;
/* 16.Find number of pixels in right margin: */
/* 17.Find total number of active pixels in image and left and right */
/* 18.Find the ideal blanking duty cycle from blanking duty cycle */
/* 19.Find the number of pixels in the blanking time to the nearest
* double character cell: */
(100000 - ideal_duty_cycle);
/* 20.Find total number of pixels: */
/* 21.Find pixel clock frequency: */
/* Stage 1 computations are now complete; I should really pass
* the results to another function and do the Stage 2 computations,
* but I only need a few more values so I'll just append the
* computations here for now */
/* 17. Find the number of pixels in the horizontal sync period: */
/* 18. Find the number of pixels in horizontal front porch period */
/* 36. Find the number of lines in the odd front porch period: */
/* finally, pack the results in the mode struct */
if (interlaced) {
}
else
return drm_mode;
}
/**
* drm_gtf_mode - create the modeline based on GTF algorithm
*
* @dev :drm device
* @hdisplay :hdisplay size
* @vdisplay :vdisplay size
* @vrefresh :vrefresh rate.
* @interlaced :whether the interlace is supported
* @margins :whether the margin is supported
*
* LOCKING.
* none.
*
* return the modeline based on GTF algorithm
*
* This function is to create the modeline based on the GTF algorithm.
* Generalized Timing Formula is derived from:
* GTF Spreadsheet by Andy Morrish (1/5/97)
* available at http://www.vesa.org
*
* What I have done is to translate it by using integer calculation.
* I also refer to the function of fb_get_mode in the file of
*
* Standard GTF parameters:
* M = 600
* C = 40
* K = 128
* J = 20
*/
struct drm_display_mode *
{
}
#ifdef CONFIG_VIDEOMODE_HELPERS
struct drm_display_mode *dmode)
{
return 0;
}
#ifdef CONFIG_OF
/**
* of_get_drm_display_mode - get a drm_display_mode from devicetree
* @np: device_node with the timing specification
* @dmode: will be set to the return value
* @index: index into the list of display timings in devicetree
*
* This function is expensive and should only be used, if only one mode is to be
* read from DT. To get multiple modes start with of_get_display_timings and
* work with that instead.
*/
{
int ret;
if (ret)
return ret;
pr_debug("%s: got %dx%d display mode from %s\n",
return 0;
}
#endif /* CONFIG_OF */
#endif /* CONFIG_VIDEOMODE_HELPERS */
/**
* drm_mode_set_name - set the name on a mode
* @mode: name will be set in this mode
*
* LOCKING:
* None.
*
* Set the name of @mode to a standard format.
*/
{
}
/**
* drm_mode_list_concat - move modes from one list to another
* @head: source list
* @new: dst list
*
* LOCKING:
* Caller must ensure both lists are locked.
*
* Move all the modes from @head to @new.
*/
{
}
}
/**
* drm_mode_width - get the width of a mode
* @mode: mode
*
* LOCKING:
* None.
*
* Return @mode's width (hdisplay) value.
*
* FIXME: is this needed?
*
* RETURNS:
* @mode->hdisplay
*/
{
}
/**
* drm_mode_height - get the height of a mode
* @mode: mode
*
* LOCKING:
* None.
*
* Return @mode's height (vdisplay) value.
*
* FIXME: is this needed?
*
* RETURNS:
* @mode->vdisplay
*/
{
}
/** drm_mode_hsync - get the hsync of a mode
* @mode: mode
*
* LOCKING:
* None.
*
* Return @modes's hsync rate in kHz, rounded to the nearest int.
*/
{
unsigned int calc_val;
return 0;
return calc_val;
}
/**
* drm_mode_vrefresh - get the vrefresh of a mode
* @mode: mode
*
* LOCKING:
* None.
*
* Return @mode's vrefresh rate in Hz or calculate it if necessary.
*
* FIXME: why is this needed? shouldn't vrefresh be set already?
*
* RETURNS:
* Vertical refresh rate. It will be the result of actual value plus 0.5.
* If it is 70.288, it will return 70Hz.
* If it is 59.6, it will return 60Hz.
*/
{
int refresh = 0;
unsigned int calc_val;
int vtotal;
/* work out vrefresh the value will be x1000 */
refresh *= 2;
refresh /= 2;
}
return refresh;
}
/**
* drm_mode_set_crtcinfo - set CRTC modesetting parameters
* @p: mode
* @adjust_flags: unused? (FIXME)
*
* LOCKING:
* None.
*
* Setup the CRTC modesetting parameters for @p, adjusting if necessary.
*/
{
return;
p->crtc_hdisplay = p->hdisplay;
p->crtc_hsync_start = p->hsync_start;
p->crtc_hsync_end = p->hsync_end;
p->crtc_htotal = p->htotal;
p->crtc_hskew = p->hskew;
p->crtc_vdisplay = p->vdisplay;
p->crtc_vsync_start = p->vsync_start;
p->crtc_vsync_end = p->vsync_end;
p->crtc_vtotal = p->vtotal;
if (p->flags & DRM_MODE_FLAG_INTERLACE) {
if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
p->crtc_vdisplay /= 2;
p->crtc_vsync_start /= 2;
p->crtc_vsync_end /= 2;
p->crtc_vtotal /= 2;
}
}
if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
p->crtc_vdisplay *= 2;
p->crtc_vsync_start *= 2;
p->crtc_vsync_end *= 2;
p->crtc_vtotal *= 2;
}
if (p->vscan > 1) {
p->crtc_vdisplay *= p->vscan;
p->crtc_vsync_start *= p->vscan;
p->crtc_vsync_end *= p->vscan;
p->crtc_vtotal *= p->vscan;
}
}
/**
* drm_mode_copy - copy the mode
* @dst: mode to overwrite
* @src: mode to copy
*
* LOCKING:
* None.
*
* Copy an existing mode into another mode, preserving the object id
* of the destination mode.
*/
{
}
/**
* drm_mode_duplicate - allocate and duplicate an existing mode
* @m: mode to duplicate
*
* LOCKING:
* None.
*
* Just allocate a new mode, copy the existing mode into it, and return
* a pointer to it. Used to create new instances of established modes.
*/
const struct drm_display_mode *mode)
{
if (!nmode)
return NULL;
return nmode;
}
/**
* drm_mode_equal - test modes for equality
* @mode1: first mode
* @mode2: second mode
*
* LOCKING:
* None.
*
* Check to see if @mode1 and @mode2 are equivalent.
*
* RETURNS:
* True if the modes are equal, false otherwise.
*/
{
/* do clock check convert to PICOS so fb modes get matched
* the same */
return false;
return false;
}
/**
* drm_mode_equal_no_clocks - test modes for equality
* @mode1: first mode
* @mode2: second mode
*
* LOCKING:
* None.
*
* Check to see if @mode1 and @mode2 are equivalent, but
* don't check the pixel clocks.
*
* RETURNS:
* True if the modes are equal, false otherwise.
*/
bool drm_mode_equal_no_clocks(const struct drm_display_mode *mode1, const struct drm_display_mode *mode2)
{
return true;
return false;
}
/**
* drm_mode_validate_size - make sure modes adhere to size constraints
* @dev: DRM device
* @mode_list: list of modes to check
* @maxX: maximum width
* @maxY: maximum height
* @maxPitch: max pitch
*
* LOCKING:
* Caller must hold a lock protecting @mode_list.
*
* The DRM device (@dev) has size and pitch limits. Here we validate the
* modes we probed for @dev against those limits and set their status as
* necessary.
*/
/* LINTED */
{
}
}
/**
* drm_mode_validate_clocks - validate modes against clock limits
* @dev: DRM device
* @mode_list: list of modes to check
* @min: minimum clock rate array
* @max: maximum clock rate array
* @n_ranges: number of clock ranges (size of arrays)
*
* LOCKING:
* Caller must hold a lock protecting @mode_list.
*
* Some code may need to check a mode list against the clock limits of the
* device in question. This function walks the mode list, testing to make
* sure each mode falls within a given range (defined by @min and @max
* arrays) and sets @mode->status as needed.
*/
/* LINTED */
{
int i;
bool good = false;
for (i = 0; i < n_ranges; i++) {
good = true;
break;
}
}
if (!good)
}
}
/**
* drm_mode_prune_invalid - remove invalid modes from mode list
* @dev: DRM device
* @mode_list: list of modes to check
* @verbose: be verbose about it
*
* LOCKING:
* Caller must hold a lock protecting @mode_list.
*
* Once mode list generation is complete, a caller can use this routine to
* remove invalid modes from a mode list. If any of the modes have a
* status other than %MODE_OK, they are removed from @mode_list and freed.
*/
{
if (verbose) {
DRM_DEBUG_KMS("Not using %s mode %d\n",
}
}
}
}
/**
* drm_mode_compare - compare modes for favorability
* @lh_a: list_head for first mode
* @lh_b: list_head for second mode
*
* LOCKING:
* None.
*
* Compare two modes, given by @lh_a and @lh_b, returning a value indicating
* which is better.
*
* RETURNS:
* Negative if @lh_a is better than @lh_b, zero if they're equivalent, or
* positive if @lh_b is better than @lh_a.
*/
{
int diff;
((a->type & DRM_MODE_TYPE_PREFERRED) != 0);
if (diff)
return diff;
if (diff)
return diff;
if (diff)
return diff;
return diff;
}
/**
* drm_mode_sort - sort mode list
* @mode_list: list to sort
*
* LOCKING:
* Caller must hold a lock protecting @mode_list.
*
* Sort @mode_list by favorability, putting good modes first.
*/
{
if (list_empty(mode_list))
return;
/* Pre-check the mode order
* In most cases, the modes is ordered.
*/
ordered = 0;
break;
}
}
if (ordered)
return;
//insert
break;
}
break;
}
}
}
}
/**
* drm_mode_connector_list_update - update the mode list for the connector
* @connector: the connector to update
*
* LOCKING:
* Caller must hold a lock protecting @mode_list.
*
* This moves the modes from the @connector probed_modes list
* to the actual mode list. It compares the probed mode against the current
* list and only adds different modes. All modes unverified after this point
* will be removed by the prune invalid modes.
*/
{
int found_it;
head) {
found_it = 0;
/* go through current modes checking for the new probed mode */
found_it = 1;
/* if equal delete the probed mode */
/* Merge type bits together */
break;
}
}
if (!found_it) {
}
}
}
struct drm_display_mode *
struct drm_cmdline_mode *cmd)
{
else
if (!mode)
return NULL;
return mode;
}