70,6 → 70,8 |
#define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) |
/* Force 8bpc */ |
#define EDID_QUIRK_FORCE_8BPC (1 << 8) |
/* Force 12bpc */ |
#define EDID_QUIRK_FORCE_12BPC (1 << 9) |
|
struct detailed_mode_closure { |
struct drm_connector *connector; |
125,6 → 127,9 |
{ "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, |
{ "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, |
|
/* Sony PVM-2541A does up to 12 bpc, but only reports max 8 bpc */ |
{ "SNY", 0x2541, EDID_QUIRK_FORCE_12BPC }, |
|
/* ViewSonic VA2026w */ |
{ "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, |
|
984,9 → 989,13 |
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 |
}; |
|
/* |
* Sanity check the header of the base EDID block. Return 8 if the header |
* is perfect, down to 0 if it's totally wrong. |
/** |
* drm_edid_header_is_valid - sanity check the header of the base EDID block |
* @raw_edid: pointer to raw base EDID block |
* |
* Sanity check the header of the base EDID block. |
* |
* Return: 8 if the header is perfect, down to 0 if it's totally wrong. |
*/ |
int drm_edid_header_is_valid(const u8 *raw_edid) |
{ |
1005,9 → 1014,16 |
MODULE_PARM_DESC(edid_fixup, |
"Minimum number of valid EDID header bytes (0-8, default 6)"); |
|
/* |
* Sanity check the EDID block (base or extension). Return 0 if the block |
* doesn't check out, or 1 if it's valid. |
/** |
* drm_edid_block_valid - Sanity check the EDID block (base or extension) |
* @raw_edid: pointer to raw EDID block |
* @block: type of block to validate (0 for base, extension otherwise) |
* @print_bad_edid: if true, dump bad EDID blocks to the console |
* |
* Validate a base or extension EDID block and optionally dump bad blocks to |
* the console. |
* |
* Return: True if the block is valid, false otherwise. |
*/ |
bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid) |
{ |
1077,6 → 1093,8 |
* @edid: EDID data |
* |
* Sanity-check an entire EDID record (including extensions) |
* |
* Return: True if the EDID data is valid, false otherwise. |
*/ |
bool drm_edid_is_valid(struct edid *edid) |
{ |
1096,14 → 1114,15 |
|
#define DDC_SEGMENT_ADDR 0x30 |
/** |
* Get EDID information via I2C. |
* drm_do_probe_ddc_edid() - get EDID information via I2C |
* @adapter: I2C device adaptor |
* @buf: EDID data buffer to be filled |
* @block: 128 byte EDID block to start fetching from |
* @len: EDID data buffer length to fetch |
* |
* \param adapter : i2c device adaptor |
* \param buf : EDID data buffer to be filled |
* \param len : EDID data buffer length |
* \return 0 on success or -1 on failure. |
* Try to fetch EDID information by calling I2C driver functions. |
* |
* Try to fetch EDID information by calling i2c driver function. |
* Return: 0 on success or -1 on failure. |
*/ |
static int |
drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf, |
1114,7 → 1133,8 |
unsigned char xfers = segment ? 3 : 2; |
int ret, retries = 5; |
|
/* The core i2c driver will automatically retry the transfer if the |
/* |
* The core I2C driver will automatically retry the transfer if the |
* adapter reports EAGAIN. However, we find that bit-banging transfers |
* are susceptible to errors under a heavily loaded machine and |
* generate spurious NAKs and timeouts. Retrying the transfer |
1141,8 → 1161,8 |
}; |
|
/* |
* Avoid sending the segment addr to not upset non-compliant ddc |
* monitors. |
* Avoid sending the segment addr to not upset non-compliant |
* DDC monitors. |
*/ |
ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers); |
|
1212,7 → 1232,7 |
if (i == 4 && print_bad_edid) { |
dev_warn(connector->dev->dev, |
"%s: Ignoring invalid EDID block %d.\n", |
drm_get_connector_name(connector), j); |
connector->name, j); |
|
connector->bad_edid_counter++; |
} |
1232,7 → 1252,7 |
carp: |
if (print_bad_edid) { |
dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n", |
drm_get_connector_name(connector), j); |
connector->name, j); |
} |
connector->bad_edid_counter++; |
|
1242,10 → 1262,10 |
} |
|
/** |
* Probe DDC presence. |
* drm_probe_ddc() - probe DDC presence |
* @adapter: I2C adapter to probe |
* |
* \param adapter : i2c device adaptor |
* \return 1 on success |
* Return: True on success, false on failure. |
*/ |
bool |
drm_probe_ddc(struct i2c_adapter *adapter) |
1259,12 → 1279,12 |
/** |
* drm_get_edid - get EDID data, if available |
* @connector: connector we're probing |
* @adapter: i2c adapter to use for DDC |
* @adapter: I2C adapter to use for DDC |
* |
* Poke the given i2c channel to grab EDID data if possible. If found, |
* Poke the given I2C channel to grab EDID data if possible. If found, |
* attach it to the connector. |
* |
* Return edid data or NULL if we couldn't find any. |
* Return: Pointer to valid EDID or NULL if we couldn't find any. |
*/ |
struct edid *drm_get_edid(struct drm_connector *connector, |
struct i2c_adapter *adapter) |
1282,7 → 1302,7 |
* drm_edid_duplicate - duplicate an EDID and the extensions |
* @edid: EDID to duplicate |
* |
* Return duplicate edid or NULL on allocation failure. |
* Return: Pointer to duplicated EDID or NULL on allocation failure. |
*/ |
struct edid *drm_edid_duplicate(const struct edid *edid) |
{ |
1405,7 → 1425,8 |
* @rb: Mode reduced-blanking-ness |
* |
* Walk the DMT mode list looking for a match for the given parameters. |
* Return a newly allocated copy of the mode, or NULL if not found. |
* |
* Return: A newly allocated copy of the mode, or NULL if not found. |
*/ |
struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, |
int hsize, int vsize, int fresh, |
1586,8 → 1607,9 |
|
/** |
* drm_mode_std - convert standard mode info (width, height, refresh) into mode |
* @connector: connector of for the EDID block |
* @edid: EDID block to scan |
* @t: standard timing params |
* @timing_level: standard timing level |
* |
* Take the standard timing params (in this case width, aspect, and refresh) |
* and convert them into a real mode using CVT/GTF/DMT. |
1594,7 → 1616,7 |
*/ |
static struct drm_display_mode * |
drm_mode_std(struct drm_connector *connector, struct edid *edid, |
struct std_timing *t, int revision) |
struct std_timing *t) |
{ |
struct drm_device *dev = connector->dev; |
struct drm_display_mode *m, *mode = NULL; |
1615,7 → 1637,7 |
vrefresh_rate = vfreq + 60; |
/* the vdisplay is calculated based on the aspect ratio */ |
if (aspect_ratio == 0) { |
if (revision < 3) |
if (edid->revision < 3) |
vsize = hsize; |
else |
vsize = (hsize * 10) / 16; |
2132,6 → 2154,7 |
|
/** |
* add_established_modes - get est. modes from EDID and add them |
* @connector: connector to add mode(s) to |
* @edid: EDID block to scan |
* |
* Each EDID block contains a bitmap of the supported "established modes" list |
2182,8 → 2205,7 |
struct drm_display_mode *newmode; |
|
std = &data->data.timings[i]; |
newmode = drm_mode_std(connector, edid, std, |
edid->revision); |
newmode = drm_mode_std(connector, edid, std); |
if (newmode) { |
drm_mode_probed_add(connector, newmode); |
closure->modes++; |
2194,6 → 2216,7 |
|
/** |
* add_standard_modes - get std. modes from EDID and add them |
* @connector: connector to add mode(s) to |
* @edid: EDID block to scan |
* |
* Standard modes can be calculated using the appropriate standard (DMT, |
2211,8 → 2234,7 |
struct drm_display_mode *newmode; |
|
newmode = drm_mode_std(connector, edid, |
&edid->standard_timings[i], |
edid->revision); |
&edid->standard_timings[i]); |
if (newmode) { |
drm_mode_probed_add(connector, newmode); |
modes++; |
2415,7 → 2437,7 |
* drm_match_cea_mode - look for a CEA mode matching given mode |
* @to_match: display mode |
* |
* Returns the CEA Video ID (VIC) of the mode or 0 if it isn't a CEA-861 |
* Return: The CEA Video ID (VIC) of the mode or 0 if it isn't a CEA-861 |
* mode. |
*/ |
u8 drm_match_cea_mode(const struct drm_display_mode *to_match) |
2442,6 → 2464,22 |
} |
EXPORT_SYMBOL(drm_match_cea_mode); |
|
/** |
* drm_get_cea_aspect_ratio - get the picture aspect ratio corresponding to |
* the input VIC from the CEA mode list |
* @video_code: ID given to each of the CEA modes |
* |
* Returns picture aspect ratio |
*/ |
enum hdmi_picture_aspect drm_get_cea_aspect_ratio(const u8 video_code) |
{ |
/* return picture aspect ratio for video_code - 1 to access the |
* right array element |
*/ |
return edid_cea_modes[video_code-1].picture_aspect_ratio; |
} |
EXPORT_SYMBOL(drm_get_cea_aspect_ratio); |
|
/* |
* Calculate the alternate clock for HDMI modes (those from the HDMI vendor |
* specific block). |
2580,6 → 2618,9 |
return NULL; |
|
newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]); |
if (!newmode) |
return NULL; |
|
newmode->vrefresh = 0; |
|
return newmode; |
3010,11 → 3051,9 |
* @connector: connector corresponding to the HDMI/DP sink |
* @edid: EDID to parse |
* |
* Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. |
* Some ELD fields are left to the graphics driver caller: |
* - Conn_Type |
* - HDCP |
* - Port_ID |
* Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The |
* Conn_Type, HDCP and Port_ID ELD fields are left for the graphics driver to |
* fill in. |
*/ |
void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) |
{ |
3098,9 → 3137,10 |
* @sads: pointer that will be set to the extracted SADs |
* |
* Looks for CEA EDID block and extracts SADs (Short Audio Descriptors) from it. |
* Note: returned pointer needs to be kfreed |
* |
* Return number of found SADs or negative number on error. |
* Note: The returned pointer needs to be freed using kfree(). |
* |
* Return: The number of found SADs or negative number on error. |
*/ |
int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads) |
{ |
3157,9 → 3197,11 |
* @sadb: pointer to the speaker block |
* |
* Looks for CEA EDID block and extracts the Speaker Allocation Data Block from it. |
* Note: returned pointer needs to be kfreed |
* |
* Return number of found Speaker Allocation Blocks or negative number on error. |
* Note: The returned pointer needs to be freed using kfree(). |
* |
* Return: The number of found Speaker Allocation Blocks or negative number on |
* error. |
*/ |
int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb) |
{ |
3191,10 → 3233,9 |
|
/* Speaker Allocation Data Block */ |
if (dbl == 3) { |
*sadb = kmalloc(dbl, GFP_KERNEL); |
*sadb = kmemdup(&db[1], dbl, GFP_KERNEL); |
if (!*sadb) |
return -ENOMEM; |
memcpy(*sadb, &db[1], dbl); |
count = dbl; |
break; |
} |
3206,9 → 3247,12 |
EXPORT_SYMBOL(drm_edid_to_speaker_allocation); |
|
/** |
* drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond |
* drm_av_sync_delay - compute the HDMI/DP sink audio-video sync delay |
* @connector: connector associated with the HDMI/DP sink |
* @mode: the display mode |
* |
* Return: The HDMI/DP sink's audio-video sync delay in milliseconds or 0 if |
* the sink doesn't support audio or video. |
*/ |
int drm_av_sync_delay(struct drm_connector *connector, |
struct drm_display_mode *mode) |
3250,6 → 3294,9 |
* |
* It's possible for one encoder to be associated with multiple HDMI/DP sinks. |
* The policy is now hard coded to simply use the first HDMI/DP sink's ELD. |
* |
* Return: The connector associated with the first HDMI/DP sink that has ELD |
* attached to it. |
*/ |
struct drm_connector *drm_select_eld(struct drm_encoder *encoder, |
struct drm_display_mode *mode) |
3257,6 → 3304,9 |
struct drm_connector *connector; |
struct drm_device *dev = encoder->dev; |
|
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); |
|
list_for_each_entry(connector, &dev->mode_config.connector_list, head) |
if (connector->encoder == encoder && connector->eld[0]) |
return connector; |
3266,11 → 3316,12 |
EXPORT_SYMBOL(drm_select_eld); |
|
/** |
* drm_detect_hdmi_monitor - detect whether monitor is hdmi. |
* drm_detect_hdmi_monitor - detect whether monitor is HDMI |
* @edid: monitor EDID information |
* |
* Parse the CEA extension according to CEA-861-B. |
* Return true if HDMI, false if not or unknown. |
* |
* Return: True if the monitor is HDMI, false if not or unknown. |
*/ |
bool drm_detect_hdmi_monitor(struct edid *edid) |
{ |
3300,6 → 3351,7 |
|
/** |
* drm_detect_monitor_audio - check monitor audio capability |
* @edid: EDID block to scan |
* |
* Monitor should have CEA extension block. |
* If monitor has 'basic audio', but no CEA audio blocks, it's 'basic |
3307,6 → 3359,7 |
* audio format, assume at least 'basic audio' support, even if 'basic |
* audio' is not defined in EDID. |
* |
* Return: True if the monitor supports audio, false otherwise. |
*/ |
bool drm_detect_monitor_audio(struct edid *edid) |
{ |
3345,10 → 3398,13 |
|
/** |
* drm_rgb_quant_range_selectable - is RGB quantization range selectable? |
* @edid: EDID block to scan |
* |
* Check whether the monitor reports the RGB quantization range selection |
* as supported. The AVI infoframe can then be used to inform the monitor |
* which quantization range (full or limited) is used. |
* |
* Return: True if the RGB quantization range is selectable, false otherwise. |
*/ |
bool drm_rgb_quant_range_selectable(struct edid *edid) |
{ |
3375,9 → 3431,111 |
EXPORT_SYMBOL(drm_rgb_quant_range_selectable); |
|
/** |
* drm_assign_hdmi_deep_color_info - detect whether monitor supports |
* hdmi deep color modes and update drm_display_info if so. |
* |
* @edid: monitor EDID information |
* @info: Updated with maximum supported deep color bpc and color format |
* if deep color supported. |
* |
* Parse the CEA extension according to CEA-861-B. |
* Return true if HDMI deep color supported, false if not or unknown. |
*/ |
static bool drm_assign_hdmi_deep_color_info(struct edid *edid, |
struct drm_display_info *info, |
struct drm_connector *connector) |
{ |
u8 *edid_ext, *hdmi; |
int i; |
int start_offset, end_offset; |
unsigned int dc_bpc = 0; |
|
edid_ext = drm_find_cea_extension(edid); |
if (!edid_ext) |
return false; |
|
if (cea_db_offsets(edid_ext, &start_offset, &end_offset)) |
return false; |
|
/* |
* Because HDMI identifier is in Vendor Specific Block, |
* search it from all data blocks of CEA extension. |
*/ |
for_each_cea_db(edid_ext, i, start_offset, end_offset) { |
if (cea_db_is_hdmi_vsdb(&edid_ext[i])) { |
/* HDMI supports at least 8 bpc */ |
info->bpc = 8; |
|
hdmi = &edid_ext[i]; |
if (cea_db_payload_len(hdmi) < 6) |
return false; |
|
if (hdmi[6] & DRM_EDID_HDMI_DC_30) { |
dc_bpc = 10; |
info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30; |
DRM_DEBUG("%s: HDMI sink does deep color 30.\n", |
connector->name); |
} |
|
if (hdmi[6] & DRM_EDID_HDMI_DC_36) { |
dc_bpc = 12; |
info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36; |
DRM_DEBUG("%s: HDMI sink does deep color 36.\n", |
connector->name); |
} |
|
if (hdmi[6] & DRM_EDID_HDMI_DC_48) { |
dc_bpc = 16; |
info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48; |
DRM_DEBUG("%s: HDMI sink does deep color 48.\n", |
connector->name); |
} |
|
if (dc_bpc > 0) { |
DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n", |
connector->name, dc_bpc); |
info->bpc = dc_bpc; |
|
/* |
* Deep color support mandates RGB444 support for all video |
* modes and forbids YCRCB422 support for all video modes per |
* HDMI 1.3 spec. |
*/ |
info->color_formats = DRM_COLOR_FORMAT_RGB444; |
|
/* YCRCB444 is optional according to spec. */ |
if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) { |
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; |
DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n", |
connector->name); |
} |
|
/* |
* Spec says that if any deep color mode is supported at all, |
* then deep color 36 bit must be supported. |
*/ |
if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) { |
DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n", |
connector->name); |
} |
|
return true; |
} |
else { |
DRM_DEBUG("%s: No deep color support on this HDMI sink.\n", |
connector->name); |
} |
} |
} |
|
return false; |
} |
|
/** |
* drm_add_display_info - pull display info out if present |
* @edid: EDID data |
* @info: display info (attached to connector) |
* @connector: connector whose edid is used to build display info |
* |
* Grab any available display info and stuff it into the drm_display_info |
* structure that's part of the connector. Useful for tracking bpp and |
3384,7 → 3542,8 |
* color spaces. |
*/ |
static void drm_add_display_info(struct edid *edid, |
struct drm_display_info *info) |
struct drm_display_info *info, |
struct drm_connector *connector) |
{ |
u8 *edid_ext; |
|
3414,6 → 3573,9 |
info->color_formats |= DRM_COLOR_FORMAT_YCRCB422; |
} |
|
/* HDMI deep color modes supported? Assign to info, if so */ |
drm_assign_hdmi_deep_color_info(edid, info, connector); |
|
/* Only defined for 1.4 with digital displays */ |
if (edid->revision < 4) |
return; |
3443,6 → 3605,9 |
break; |
} |
|
DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n", |
connector->name, info->bpc); |
|
info->color_formats |= DRM_COLOR_FORMAT_RGB444; |
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444) |
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444; |
3453,11 → 3618,11 |
/** |
* drm_add_edid_modes - add modes from EDID data, if available |
* @connector: connector we're probing |
* @edid: edid data |
* @edid: EDID data |
* |
* Add the specified modes to the connector's mode list. |
* |
* Return number of modes added or 0 if we couldn't find any. |
* Return: The number of modes added or 0 if we couldn't find any. |
*/ |
int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) |
{ |
3469,7 → 3634,7 |
} |
if (!drm_edid_is_valid(edid)) { |
dev_warn(connector->dev->dev, "%s: EDID invalid.\n", |
drm_get_connector_name(connector)); |
connector->name); |
return 0; |
} |
|
3501,11 → 3666,14 |
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) |
edid_fixup_preferred(connector, quirks); |
|
drm_add_display_info(edid, &connector->display_info); |
drm_add_display_info(edid, &connector->display_info, connector); |
|
if (quirks & EDID_QUIRK_FORCE_8BPC) |
connector->display_info.bpc = 8; |
|
if (quirks & EDID_QUIRK_FORCE_12BPC) |
connector->display_info.bpc = 12; |
|
return num_modes; |
} |
EXPORT_SYMBOL(drm_add_edid_modes); |
3519,7 → 3687,7 |
* Add the specified modes to the connector's mode list. Only when the |
* hdisplay/vdisplay is not beyond the given limit, it will be added. |
* |
* Return number of modes added or 0 if we couldn't find any. |
* Return: The number of modes added or 0 if we couldn't find any. |
*/ |
int drm_add_modes_noedid(struct drm_connector *connector, |
int hdisplay, int vdisplay) |
3558,6 → 3726,15 |
} |
EXPORT_SYMBOL(drm_add_modes_noedid); |
|
/** |
* 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) |
{ |
3564,8 → 3741,8 |
struct drm_display_mode *mode; |
|
list_for_each_entry(mode, &connector->probed_modes, head) { |
if (drm_mode_width(mode) == hpref && |
drm_mode_height(mode) == vpref) |
if (mode->hdisplay == hpref && |
mode->vdisplay == vpref) |
mode->type |= DRM_MODE_TYPE_PREFERRED; |
} |
} |
3577,7 → 3754,7 |
* @frame: HDMI AVI infoframe |
* @mode: DRM display mode |
* |
* Returns 0 on success or a negative error code on failure. |
* Return: 0 on success or a negative error code on failure. |
*/ |
int |
drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame, |
3598,7 → 3775,20 |
frame->video_code = drm_match_cea_mode(mode); |
|
frame->picture_aspect = HDMI_PICTURE_ASPECT_NONE; |
|
/* |
* Populate picture aspect ratio from either |
* user input (if specified) or from the CEA mode list. |
*/ |
if (mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_4_3 || |
mode->picture_aspect_ratio == HDMI_PICTURE_ASPECT_16_9) |
frame->picture_aspect = mode->picture_aspect_ratio; |
else if (frame->video_code > 0) |
frame->picture_aspect = drm_get_cea_aspect_ratio( |
frame->video_code); |
|
frame->active_aspect = HDMI_ACTIVE_ASPECT_PICTURE; |
frame->scan_mode = HDMI_SCAN_MODE_UNDERSCAN; |
|
return 0; |
} |
3641,7 → 3831,7 |
* 4k or stereoscopic 3D mode. So when giving any other mode as input this |
* function will return -EINVAL, error that can be safely ignored. |
* |
* Returns 0 on success or a negative error code on failure. |
* Return: 0 on success or a negative error code on failure. |
*/ |
int |
drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame, |