Merge tag 'topic/drm-misc-2016-10-05' of git://anongit.freedesktop.org/drm-intel into drm-next
Another attempt, this time rebased and without the pipe crc patches: - display_info cleanups from Ville - make prime/gem lookups faster with rbtrees (Chris) - misc stuff all over * tag 'topic/drm-misc-2016-10-05' of git://anongit.freedesktop.org/drm-intel: drm/rockchip: analogix_dp: Refuse to enable PSR if panel doesn't support it drm/bridge: analogix_dp: Add analogix_dp_psr_supported drm/fb-helper: add DRM_FB_HELPER_DEFAULT_OPS for fb_ops drm: Document caveats around atomic event handling uapi: add missing install of sync_file.h drm: Simplify drm_printk to reduce object size quite a bit drm/i915: Account for sink max TMDS clock when checking the port clock drm/i915: Replace a bunch of connector->base.display_info with a local variable drm/edid: Move dvi_dual/max_tmds_clock parsing out from drm_edid_to_eld() drm/edid: Clear the old cea_rev when there's no CEA extension in the new EDID drm/edid: Reduce the number of times we parse the CEA extension block drm/edid: Don't pass around drm_display_info needlessly drm/edid: Move dvi_dual/max_tmds_clock to drm_display_info drm/edid: Make max_tmds_clock kHz instead of MHz drm/edid: Clear old dvi_dual/max_tmds_clock before parsing the new EDID drm/edid: Clear old audio latency values before parsing the new EDID drm: Convert prime dma-buf <-> handle to rbtree drm/mediatek: mark symbols static where possible drm/rockchip: mark symbols static where possible drm/rockchip: add missing header dependencies
This commit is contained in:
Коммит
9c704d1438
|
@ -168,12 +168,12 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
|||
}
|
||||
|
||||
/* Any defined maximum tmds clock limit we must not exceed? */
|
||||
if (connector->max_tmds_clock > 0) {
|
||||
if (connector->display_info.max_tmds_clock > 0) {
|
||||
/* mode_clock is clock in kHz for mode to be modeset on this connector */
|
||||
mode_clock = amdgpu_connector->pixelclock_for_modeset;
|
||||
|
||||
/* Maximum allowable input clock in kHz */
|
||||
max_tmds_clock = connector->max_tmds_clock * 1000;
|
||||
max_tmds_clock = connector->display_info.max_tmds_clock;
|
||||
|
||||
DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
|
||||
connector->name, mode_clock, max_tmds_clock);
|
||||
|
|
|
@ -98,6 +98,14 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int analogix_dp_psr_supported(struct device *dev)
|
||||
{
|
||||
struct analogix_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
||||
return dp->psr_support;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(analogix_dp_psr_supported);
|
||||
|
||||
int analogix_dp_enable_psr(struct device *dev)
|
||||
{
|
||||
struct analogix_dp_device *dp = dev_get_drvdata(dev);
|
||||
|
|
|
@ -89,7 +89,6 @@ void drm_dev_printk(const struct device *dev, const char *level,
|
|||
EXPORT_SYMBOL(drm_dev_printk);
|
||||
|
||||
void drm_printk(const char *level, unsigned int category,
|
||||
const char *function_name, const char *prefix,
|
||||
const char *format, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
|
@ -102,7 +101,9 @@ void drm_printk(const char *level, unsigned int category,
|
|||
vaf.fmt = format;
|
||||
vaf.va = &args;
|
||||
|
||||
printk("%s" DRM_PRINTK_FMT, level, function_name, prefix, &vaf);
|
||||
printk("%s" "[" DRM_NAME ":%ps]%s %pV",
|
||||
level, __builtin_return_address(0),
|
||||
strcmp(level, KERN_ERR) == 0 ? " *ERROR*" : "", &vaf);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
|
|
@ -3253,16 +3253,12 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
|
|||
}
|
||||
|
||||
static void
|
||||
parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
|
||||
drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
|
||||
{
|
||||
u8 len = cea_db_payload_len(db);
|
||||
|
||||
if (len >= 6) {
|
||||
if (len >= 6)
|
||||
connector->eld[5] |= (db[6] >> 7) << 1; /* Supports_AI */
|
||||
connector->dvi_dual = db[6] & 1;
|
||||
}
|
||||
if (len >= 7)
|
||||
connector->max_tmds_clock = db[7] * 5;
|
||||
if (len >= 8) {
|
||||
connector->latency_present[0] = db[8] >> 7;
|
||||
connector->latency_present[1] = (db[8] >> 6) & 1;
|
||||
|
@ -3276,19 +3272,15 @@ parse_hdmi_vsdb(struct drm_connector *connector, const u8 *db)
|
|||
if (len >= 12)
|
||||
connector->audio_latency[1] = db[12];
|
||||
|
||||
DRM_DEBUG_KMS("HDMI: DVI dual %d, "
|
||||
"max TMDS clock %d, "
|
||||
"latency present %d %d, "
|
||||
"video latency %d %d, "
|
||||
"audio latency %d %d\n",
|
||||
connector->dvi_dual,
|
||||
connector->max_tmds_clock,
|
||||
(int) connector->latency_present[0],
|
||||
(int) connector->latency_present[1],
|
||||
connector->video_latency[0],
|
||||
connector->video_latency[1],
|
||||
connector->audio_latency[0],
|
||||
connector->audio_latency[1]);
|
||||
DRM_DEBUG_KMS("HDMI: latency present %d %d, "
|
||||
"video latency %d %d, "
|
||||
"audio latency %d %d\n",
|
||||
connector->latency_present[0],
|
||||
connector->latency_present[1],
|
||||
connector->video_latency[0],
|
||||
connector->video_latency[1],
|
||||
connector->audio_latency[0],
|
||||
connector->audio_latency[1]);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -3358,6 +3350,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
|||
|
||||
memset(eld, 0, sizeof(connector->eld));
|
||||
|
||||
connector->latency_present[0] = false;
|
||||
connector->latency_present[1] = false;
|
||||
connector->video_latency[0] = 0;
|
||||
connector->audio_latency[0] = 0;
|
||||
connector->video_latency[1] = 0;
|
||||
connector->audio_latency[1] = 0;
|
||||
|
||||
cea = drm_find_cea_extension(edid);
|
||||
if (!cea) {
|
||||
DRM_DEBUG_KMS("ELD: no CEA Extension found\n");
|
||||
|
@ -3407,7 +3406,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
|||
case VENDOR_BLOCK:
|
||||
/* HDMI Vendor-Specific Data Block */
|
||||
if (cea_db_is_hdmi_vsdb(db))
|
||||
parse_hdmi_vsdb(connector, db);
|
||||
drm_parse_hdmi_vsdb_audio(connector, db);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -3721,105 +3720,127 @@ bool drm_rgb_quant_range_selectable(struct edid *edid)
|
|||
}
|
||||
EXPORT_SYMBOL(drm_rgb_quant_range_selectable);
|
||||
|
||||
/*
|
||||
* 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)
|
||||
static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
|
||||
const u8 *hdmi)
|
||||
{
|
||||
u8 *edid_ext, *hdmi;
|
||||
int i;
|
||||
int start_offset, end_offset;
|
||||
struct drm_display_info *info = &connector->display_info;
|
||||
unsigned int dc_bpc = 0;
|
||||
|
||||
/* HDMI supports at least 8 bpc */
|
||||
info->bpc = 8;
|
||||
|
||||
if (cea_db_payload_len(hdmi) < 6)
|
||||
return;
|
||||
|
||||
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: No deep color support on this HDMI sink.\n",
|
||||
connector->name);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
|
||||
{
|
||||
struct drm_display_info *info = &connector->display_info;
|
||||
u8 len = cea_db_payload_len(db);
|
||||
|
||||
if (len >= 6)
|
||||
info->dvi_dual = db[6] & 1;
|
||||
if (len >= 7)
|
||||
info->max_tmds_clock = db[7] * 5000;
|
||||
|
||||
DRM_DEBUG_KMS("HDMI: DVI dual %d, "
|
||||
"max TMDS clock %d kHz\n",
|
||||
info->dvi_dual,
|
||||
info->max_tmds_clock);
|
||||
|
||||
drm_parse_hdmi_deep_color_info(connector, db);
|
||||
}
|
||||
|
||||
static void drm_parse_cea_ext(struct drm_connector *connector,
|
||||
struct edid *edid)
|
||||
{
|
||||
struct drm_display_info *info = &connector->display_info;
|
||||
const u8 *edid_ext;
|
||||
int i, start, end;
|
||||
|
||||
edid_ext = drm_find_cea_extension(edid);
|
||||
if (!edid_ext)
|
||||
return false;
|
||||
return;
|
||||
|
||||
if (cea_db_offsets(edid_ext, &start_offset, &end_offset))
|
||||
return false;
|
||||
info->cea_rev = edid_ext[1];
|
||||
|
||||
/*
|
||||
* 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;
|
||||
/* The existence of a CEA block should imply RGB support */
|
||||
info->color_formats = DRM_COLOR_FORMAT_RGB444;
|
||||
if (edid_ext[3] & EDID_CEA_YCRCB444)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
|
||||
if (edid_ext[3] & EDID_CEA_YCRCB422)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
|
||||
|
||||
hdmi = &edid_ext[i];
|
||||
if (cea_db_payload_len(hdmi) < 6)
|
||||
return false;
|
||||
if (cea_db_offsets(edid_ext, &start, &end))
|
||||
return;
|
||||
|
||||
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);
|
||||
}
|
||||
for_each_cea_db(edid_ext, i, start, end) {
|
||||
const u8 *db = &edid_ext[i];
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if (cea_db_is_hdmi_vsdb(db))
|
||||
drm_parse_hdmi_vsdb_video(connector, db);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void drm_add_display_info(struct edid *edid,
|
||||
struct drm_display_info *info,
|
||||
struct drm_connector *connector)
|
||||
static void drm_add_display_info(struct drm_connector *connector,
|
||||
struct edid *edid)
|
||||
{
|
||||
u8 *edid_ext;
|
||||
struct drm_display_info *info = &connector->display_info;
|
||||
|
||||
info->width_mm = edid->width_cm * 10;
|
||||
info->height_mm = edid->height_cm * 10;
|
||||
|
@ -3827,6 +3848,9 @@ static void drm_add_display_info(struct edid *edid,
|
|||
/* driver figures it out in this case */
|
||||
info->bpc = 0;
|
||||
info->color_formats = 0;
|
||||
info->cea_rev = 0;
|
||||
info->max_tmds_clock = 0;
|
||||
info->dvi_dual = false;
|
||||
|
||||
if (edid->revision < 3)
|
||||
return;
|
||||
|
@ -3834,21 +3858,7 @@ static void drm_add_display_info(struct edid *edid,
|
|||
if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
|
||||
return;
|
||||
|
||||
/* Get data from CEA blocks if present */
|
||||
edid_ext = drm_find_cea_extension(edid);
|
||||
if (edid_ext) {
|
||||
info->cea_rev = edid_ext[1];
|
||||
|
||||
/* The existence of a CEA block should imply RGB support */
|
||||
info->color_formats = DRM_COLOR_FORMAT_RGB444;
|
||||
if (edid_ext[3] & EDID_CEA_YCRCB444)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
|
||||
if (edid_ext[3] & EDID_CEA_YCRCB422)
|
||||
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);
|
||||
drm_parse_cea_ext(connector, edid);
|
||||
|
||||
/*
|
||||
* Digital sink with "DFP 1.x compliant TMDS" according to EDID 1.3?
|
||||
|
@ -4084,7 +4094,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
|
|||
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, connector);
|
||||
drm_add_display_info(connector, edid);
|
||||
|
||||
if (quirks & EDID_QUIRK_FORCE_6BPC)
|
||||
connector->display_info.bpc = 6;
|
||||
|
|
|
@ -1008,6 +1008,31 @@ static void send_vblank_event(struct drm_device *dev,
|
|||
* period. This helper function implements exactly the required vblank arming
|
||||
* behaviour.
|
||||
*
|
||||
* NOTE: Drivers using this to send out the event in struct &drm_crtc_state
|
||||
* as part of an atomic commit must ensure that the next vblank happens at
|
||||
* exactly the same time as the atomic commit is committed to the hardware. This
|
||||
* function itself does **not** protect again the next vblank interrupt racing
|
||||
* with either this function call or the atomic commit operation. A possible
|
||||
* sequence could be:
|
||||
*
|
||||
* 1. Driver commits new hardware state into vblank-synchronized registers.
|
||||
* 2. A vblank happens, committing the hardware state. Also the corresponding
|
||||
* vblank interrupt is fired off and fully processed by the interrupt
|
||||
* handler.
|
||||
* 3. The atomic commit operation proceeds to call drm_crtc_arm_vblank_event().
|
||||
* 4. The event is only send out for the next vblank, which is wrong.
|
||||
*
|
||||
* An equivalent race can happen when the driver calls
|
||||
* drm_crtc_arm_vblank_event() before writing out the new hardware state.
|
||||
*
|
||||
* The only way to make this work safely is to prevent the vblank from firing
|
||||
* (and the hardware from committing anything else) until the entire atomic
|
||||
* commit sequence has run to completion. If the hardware does not have such a
|
||||
* feature (e.g. using a "go" bit), then it is unsafe to use this functions.
|
||||
* Instead drivers need to manually send out the event from their interrupt
|
||||
* handler by calling drm_crtc_send_vblank_event() and make sure that there's no
|
||||
* possible race with the hardware committing the atomic update.
|
||||
*
|
||||
* Caller must hold event lock. Caller must also hold a vblank reference for
|
||||
* the event @e, which will be dropped when the next vblank arrives.
|
||||
*/
|
||||
|
@ -1030,8 +1055,11 @@ EXPORT_SYMBOL(drm_crtc_arm_vblank_event);
|
|||
* @crtc: the source CRTC of the vblank event
|
||||
* @e: the event to send
|
||||
*
|
||||
* Updates sequence # and timestamp on event, and sends it to userspace.
|
||||
* Caller must hold event lock.
|
||||
* Updates sequence # and timestamp on event for the most recently processed
|
||||
* vblank, and sends it to userspace. Caller must hold event lock.
|
||||
*
|
||||
* See drm_crtc_arm_vblank_event() for a helper which can be used in certain
|
||||
* situation, especially to send out events for atomic commit operations.
|
||||
*/
|
||||
void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
|
||||
struct drm_pending_vblank_event *e)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <linux/export.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_gem.h>
|
||||
|
||||
|
@ -61,9 +62,11 @@
|
|||
*/
|
||||
|
||||
struct drm_prime_member {
|
||||
struct list_head entry;
|
||||
struct dma_buf *dma_buf;
|
||||
uint32_t handle;
|
||||
|
||||
struct rb_node dmabuf_rb;
|
||||
struct rb_node handle_rb;
|
||||
};
|
||||
|
||||
struct drm_prime_attachment {
|
||||
|
@ -75,6 +78,7 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
|
|||
struct dma_buf *dma_buf, uint32_t handle)
|
||||
{
|
||||
struct drm_prime_member *member;
|
||||
struct rb_node **p, *rb;
|
||||
|
||||
member = kmalloc(sizeof(*member), GFP_KERNEL);
|
||||
if (!member)
|
||||
|
@ -83,18 +87,56 @@ static int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv,
|
|||
get_dma_buf(dma_buf);
|
||||
member->dma_buf = dma_buf;
|
||||
member->handle = handle;
|
||||
list_add(&member->entry, &prime_fpriv->head);
|
||||
|
||||
rb = NULL;
|
||||
p = &prime_fpriv->dmabufs.rb_node;
|
||||
while (*p) {
|
||||
struct drm_prime_member *pos;
|
||||
|
||||
rb = *p;
|
||||
pos = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
|
||||
if (dma_buf > pos->dma_buf)
|
||||
p = &rb->rb_right;
|
||||
else
|
||||
p = &rb->rb_left;
|
||||
}
|
||||
rb_link_node(&member->dmabuf_rb, rb, p);
|
||||
rb_insert_color(&member->dmabuf_rb, &prime_fpriv->dmabufs);
|
||||
|
||||
rb = NULL;
|
||||
p = &prime_fpriv->handles.rb_node;
|
||||
while (*p) {
|
||||
struct drm_prime_member *pos;
|
||||
|
||||
rb = *p;
|
||||
pos = rb_entry(rb, struct drm_prime_member, handle_rb);
|
||||
if (handle > pos->handle)
|
||||
p = &rb->rb_right;
|
||||
else
|
||||
p = &rb->rb_left;
|
||||
}
|
||||
rb_link_node(&member->handle_rb, rb, p);
|
||||
rb_insert_color(&member->handle_rb, &prime_fpriv->handles);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct dma_buf *drm_prime_lookup_buf_by_handle(struct drm_prime_file_private *prime_fpriv,
|
||||
uint32_t handle)
|
||||
{
|
||||
struct drm_prime_member *member;
|
||||
struct rb_node *rb;
|
||||
|
||||
list_for_each_entry(member, &prime_fpriv->head, entry) {
|
||||
rb = prime_fpriv->handles.rb_node;
|
||||
while (rb) {
|
||||
struct drm_prime_member *member;
|
||||
|
||||
member = rb_entry(rb, struct drm_prime_member, handle_rb);
|
||||
if (member->handle == handle)
|
||||
return member->dma_buf;
|
||||
else if (member->handle < handle)
|
||||
rb = rb->rb_right;
|
||||
else
|
||||
rb = rb->rb_left;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -104,14 +146,23 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
|
|||
struct dma_buf *dma_buf,
|
||||
uint32_t *handle)
|
||||
{
|
||||
struct drm_prime_member *member;
|
||||
struct rb_node *rb;
|
||||
|
||||
list_for_each_entry(member, &prime_fpriv->head, entry) {
|
||||
rb = prime_fpriv->dmabufs.rb_node;
|
||||
while (rb) {
|
||||
struct drm_prime_member *member;
|
||||
|
||||
member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
|
||||
if (member->dma_buf == dma_buf) {
|
||||
*handle = member->handle;
|
||||
return 0;
|
||||
} else if (member->dma_buf < dma_buf) {
|
||||
rb = rb->rb_right;
|
||||
} else {
|
||||
rb = rb->rb_left;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@ -166,13 +217,24 @@ static void drm_gem_map_detach(struct dma_buf *dma_buf,
|
|||
void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
|
||||
struct dma_buf *dma_buf)
|
||||
{
|
||||
struct drm_prime_member *member, *safe;
|
||||
struct rb_node *rb;
|
||||
|
||||
list_for_each_entry_safe(member, safe, &prime_fpriv->head, entry) {
|
||||
rb = prime_fpriv->dmabufs.rb_node;
|
||||
while (rb) {
|
||||
struct drm_prime_member *member;
|
||||
|
||||
member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
|
||||
if (member->dma_buf == dma_buf) {
|
||||
rb_erase(&member->handle_rb, &prime_fpriv->handles);
|
||||
rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
|
||||
|
||||
dma_buf_put(dma_buf);
|
||||
list_del(&member->entry);
|
||||
kfree(member);
|
||||
return;
|
||||
} else if (member->dma_buf < dma_buf) {
|
||||
rb = rb->rb_right;
|
||||
} else {
|
||||
rb = rb->rb_left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -759,12 +821,13 @@ EXPORT_SYMBOL(drm_prime_gem_destroy);
|
|||
|
||||
void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
|
||||
{
|
||||
INIT_LIST_HEAD(&prime_fpriv->head);
|
||||
mutex_init(&prime_fpriv->lock);
|
||||
prime_fpriv->dmabufs = RB_ROOT;
|
||||
prime_fpriv->handles = RB_ROOT;
|
||||
}
|
||||
|
||||
void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv)
|
||||
{
|
||||
/* by now drm_gem_release should've made sure the list is empty */
|
||||
WARN_ON(!list_empty(&prime_fpriv->head));
|
||||
WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs));
|
||||
}
|
||||
|
|
|
@ -12654,22 +12654,22 @@ static void
|
|||
connected_sink_compute_bpp(struct intel_connector *connector,
|
||||
struct intel_crtc_state *pipe_config)
|
||||
{
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
int bpp = pipe_config->pipe_bpp;
|
||||
|
||||
DRM_DEBUG_KMS("[CONNECTOR:%d:%s] checking for sink bpp constrains\n",
|
||||
connector->base.base.id,
|
||||
connector->base.name);
|
||||
connector->base.base.id,
|
||||
connector->base.name);
|
||||
|
||||
/* Don't use an invalid EDID bpc value */
|
||||
if (connector->base.display_info.bpc &&
|
||||
connector->base.display_info.bpc * 3 < bpp) {
|
||||
if (info->bpc != 0 && info->bpc * 3 < bpp) {
|
||||
DRM_DEBUG_KMS("clamping display bpp (was %d) to EDID reported max of %d\n",
|
||||
bpp, connector->base.display_info.bpc*3);
|
||||
pipe_config->pipe_bpp = connector->base.display_info.bpc*3;
|
||||
bpp, info->bpc * 3);
|
||||
pipe_config->pipe_bpp = info->bpc * 3;
|
||||
}
|
||||
|
||||
/* Clamp bpp to 8 on screens without EDID 1.4 */
|
||||
if (connector->base.display_info.bpc == 0 && bpp > 24) {
|
||||
if (info->bpc == 0 && bpp > 24) {
|
||||
DRM_DEBUG_KMS("clamping display bpp (was %d) to default limit of 24\n",
|
||||
bpp);
|
||||
pipe_config->pipe_bpp = 24;
|
||||
|
|
|
@ -1220,10 +1220,17 @@ static int hdmi_port_clock_limit(struct intel_hdmi *hdmi,
|
|||
int max_tmds_clock = intel_hdmi_source_max_tmds_clock(to_i915(dev));
|
||||
|
||||
if (respect_downstream_limits) {
|
||||
struct intel_connector *connector = hdmi->attached_connector;
|
||||
const struct drm_display_info *info = &connector->base.display_info;
|
||||
|
||||
if (hdmi->dp_dual_mode.max_tmds_clock)
|
||||
max_tmds_clock = min(max_tmds_clock,
|
||||
hdmi->dp_dual_mode.max_tmds_clock);
|
||||
if (!hdmi->has_hdmi_sink)
|
||||
|
||||
if (info->max_tmds_clock)
|
||||
max_tmds_clock = min(max_tmds_clock,
|
||||
info->max_tmds_clock);
|
||||
else if (!hdmi->has_hdmi_sink)
|
||||
max_tmds_clock = min(max_tmds_clock, 165000);
|
||||
}
|
||||
|
||||
|
|
|
@ -1086,20 +1086,20 @@ static int mtk_hdmi_output_init(struct mtk_hdmi *hdmi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void mtk_hdmi_audio_enable(struct mtk_hdmi *hdmi)
|
||||
static void mtk_hdmi_audio_enable(struct mtk_hdmi *hdmi)
|
||||
{
|
||||
mtk_hdmi_aud_enable_packet(hdmi, true);
|
||||
hdmi->audio_enable = true;
|
||||
}
|
||||
|
||||
void mtk_hdmi_audio_disable(struct mtk_hdmi *hdmi)
|
||||
static void mtk_hdmi_audio_disable(struct mtk_hdmi *hdmi)
|
||||
{
|
||||
mtk_hdmi_aud_enable_packet(hdmi, false);
|
||||
hdmi->audio_enable = false;
|
||||
}
|
||||
|
||||
int mtk_hdmi_audio_set_param(struct mtk_hdmi *hdmi,
|
||||
struct hdmi_audio_param *param)
|
||||
static int mtk_hdmi_audio_set_param(struct mtk_hdmi *hdmi,
|
||||
struct hdmi_audio_param *param)
|
||||
{
|
||||
if (!hdmi->audio_enable) {
|
||||
dev_err(hdmi->dev, "hdmi audio is in disable state!\n");
|
||||
|
@ -1624,7 +1624,8 @@ static void mtk_hdmi_audio_shutdown(struct device *dev, void *data)
|
|||
mtk_hdmi_audio_disable(hdmi);
|
||||
}
|
||||
|
||||
int mtk_hdmi_audio_digital_mute(struct device *dev, void *data, bool enable)
|
||||
static int
|
||||
mtk_hdmi_audio_digital_mute(struct device *dev, void *data, bool enable)
|
||||
{
|
||||
struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
|
||||
|
||||
|
|
|
@ -198,12 +198,12 @@ int radeon_get_monitor_bpc(struct drm_connector *connector)
|
|||
}
|
||||
|
||||
/* Any defined maximum tmds clock limit we must not exceed? */
|
||||
if (connector->max_tmds_clock > 0) {
|
||||
if (connector->display_info.max_tmds_clock > 0) {
|
||||
/* mode_clock is clock in kHz for mode to be modeset on this connector */
|
||||
mode_clock = radeon_connector->pixelclock_for_modeset;
|
||||
|
||||
/* Maximum allowable input clock in kHz */
|
||||
max_tmds_clock = connector->max_tmds_clock * 1000;
|
||||
max_tmds_clock = connector->display_info.max_tmds_clock;
|
||||
|
||||
DRM_DEBUG("%s: hdmi mode dotclock %d kHz, max tmds input clock %d kHz.\n",
|
||||
connector->name, mode_clock, max_tmds_clock);
|
||||
|
|
|
@ -85,6 +85,9 @@ static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled)
|
|||
struct rockchip_dp_device *dp = to_dp(encoder);
|
||||
unsigned long flags;
|
||||
|
||||
if (!analogix_dp_psr_supported(dp->dev))
|
||||
return;
|
||||
|
||||
dev_dbg(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit");
|
||||
|
||||
spin_lock_irqsave(&dp->psr_lock, flags);
|
||||
|
|
|
@ -309,7 +309,7 @@ static struct drm_driver rockchip_drm_driver = {
|
|||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
void rockchip_drm_fb_suspend(struct drm_device *drm)
|
||||
static void rockchip_drm_fb_suspend(struct drm_device *drm)
|
||||
{
|
||||
struct rockchip_drm_private *priv = drm->dev_private;
|
||||
|
||||
|
@ -318,7 +318,7 @@ void rockchip_drm_fb_suspend(struct drm_device *drm)
|
|||
console_unlock();
|
||||
}
|
||||
|
||||
void rockchip_drm_fb_resume(struct drm_device *drm)
|
||||
static void rockchip_drm_fb_resume(struct drm_device *drm)
|
||||
{
|
||||
struct rockchip_drm_private *priv = drm->dev_private;
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "rockchip_drm_drv.h"
|
||||
#include "rockchip_drm_gem.h"
|
||||
#include "rockchip_drm_fb.h"
|
||||
#include "rockchip_drm_fbdev.h"
|
||||
|
||||
#define PREFERRED_BPP 32
|
||||
#define to_drm_private(x) \
|
||||
|
|
|
@ -38,6 +38,7 @@ struct analogix_dp_plat_data {
|
|||
struct drm_connector *);
|
||||
};
|
||||
|
||||
int analogix_dp_psr_supported(struct device *dev);
|
||||
int analogix_dp_enable_psr(struct device *dev);
|
||||
int analogix_dp_disable_psr(struct device *dev);
|
||||
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/poll.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/rbtree.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
@ -140,9 +141,8 @@ void drm_dev_printk(const struct device *dev, const char *level,
|
|||
unsigned int category, const char *function_name,
|
||||
const char *prefix, const char *format, ...);
|
||||
|
||||
extern __printf(5, 6)
|
||||
extern __printf(3, 4)
|
||||
void drm_printk(const char *level, unsigned int category,
|
||||
const char *function_name, const char *prefix,
|
||||
const char *format, ...);
|
||||
|
||||
/***********************************************************************/
|
||||
|
@ -198,8 +198,7 @@ void drm_printk(const char *level, unsigned int category,
|
|||
drm_dev_printk(dev, KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*",\
|
||||
fmt, ##__VA_ARGS__)
|
||||
#define DRM_ERROR(fmt, ...) \
|
||||
drm_printk(KERN_ERR, DRM_UT_NONE, __func__, " *ERROR*", fmt, \
|
||||
##__VA_ARGS__)
|
||||
drm_printk(KERN_ERR, DRM_UT_NONE, fmt, ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* Rate limited error output. Like DRM_ERROR() but won't flood the log.
|
||||
|
@ -241,38 +240,38 @@ void drm_printk(const char *level, unsigned int category,
|
|||
#define DRM_DEV_DEBUG(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, \
|
||||
##args)
|
||||
#define DRM_DEBUG(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_CORE, __func__, "", fmt, ##args)
|
||||
#define DRM_DEBUG(fmt, ...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_CORE, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DRM_DEV_DEBUG_DRIVER(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_DRIVER, __func__, "", \
|
||||
fmt, ##args)
|
||||
#define DRM_DEBUG_DRIVER(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_DRIVER, __func__, "", fmt, ##args)
|
||||
#define DRM_DEBUG_DRIVER(fmt, ...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_DRIVER, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DRM_DEV_DEBUG_KMS(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, \
|
||||
##args)
|
||||
#define DRM_DEBUG_KMS(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_KMS, __func__, "", fmt, ##args)
|
||||
#define DRM_DEBUG_KMS(fmt, ...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_KMS, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DRM_DEV_DEBUG_PRIME(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_PRIME, __func__, "", \
|
||||
fmt, ##args)
|
||||
#define DRM_DEBUG_PRIME(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_PRIME, __func__, "", fmt, ##args)
|
||||
#define DRM_DEBUG_PRIME(fmt, ...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_PRIME, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DRM_DEV_DEBUG_ATOMIC(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", \
|
||||
fmt, ##args)
|
||||
#define DRM_DEBUG_ATOMIC(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, __func__, "", fmt, ##args)
|
||||
#define DRM_DEBUG_ATOMIC(fmt, ...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_ATOMIC, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define DRM_DEV_DEBUG_VBL(dev, fmt, args...) \
|
||||
drm_dev_printk(dev, KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, \
|
||||
##args)
|
||||
#define DRM_DEBUG_VBL(fmt, args...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_VBL, __func__, "", fmt, ##args)
|
||||
#define DRM_DEBUG_VBL(fmt, ...) \
|
||||
drm_printk(KERN_DEBUG, DRM_UT_VBL, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...) \
|
||||
({ \
|
||||
|
@ -371,10 +370,10 @@ struct drm_pending_event {
|
|||
we deliver the event, for tracing only */
|
||||
};
|
||||
|
||||
/* initial implementaton using a linked list - todo hashtab */
|
||||
struct drm_prime_file_private {
|
||||
struct list_head head;
|
||||
struct mutex lock;
|
||||
struct rb_root dmabufs;
|
||||
struct rb_root handles;
|
||||
};
|
||||
|
||||
/** File private data */
|
||||
|
|
|
@ -166,6 +166,17 @@ struct drm_display_info {
|
|||
*/
|
||||
u32 bus_flags;
|
||||
|
||||
/**
|
||||
* @max_tmds_clock: Maximum TMDS clock rate supported by the
|
||||
* sink in kHz. 0 means undefined.
|
||||
*/
|
||||
int max_tmds_clock;
|
||||
|
||||
/**
|
||||
* @dvi_dual: Dual-link DVI sink?
|
||||
*/
|
||||
bool dvi_dual;
|
||||
|
||||
/**
|
||||
* @edid_hdmi_dc_modes: Mask of supported hdmi deep color modes. Even
|
||||
* more stuff redundant with @bus_formats.
|
||||
|
@ -515,8 +526,6 @@ struct drm_cmdline_mode {
|
|||
* @encoder_ids: valid encoders for this connector
|
||||
* @encoder: encoder driving this connector, if any
|
||||
* @eld: EDID-like data, if present
|
||||
* @dvi_dual: dual link DVI, if found
|
||||
* @max_tmds_clock: max clock rate, if found
|
||||
* @latency_present: AV delay info from ELD, if found
|
||||
* @video_latency: video latency info from ELD, if found
|
||||
* @audio_latency: audio latency info from ELD, if found
|
||||
|
@ -650,8 +659,6 @@ struct drm_connector {
|
|||
#define MAX_ELD_BYTES 128
|
||||
/* EDID bits */
|
||||
uint8_t eld[MAX_ELD_BYTES];
|
||||
bool dvi_dual;
|
||||
int max_tmds_clock; /* in MHz */
|
||||
bool latency_present[2];
|
||||
int video_latency[2]; /* [0]: progressive, [1]: interlaced */
|
||||
int audio_latency[2];
|
||||
|
|
|
@ -109,8 +109,6 @@ struct drm_plane_helper_funcs;
|
|||
* @ctm: Transformation matrix
|
||||
* @gamma_lut: Lookup table for converting pixel data after the
|
||||
* conversion matrix
|
||||
* @event: optional pointer to a DRM event to signal upon completion of the
|
||||
* state update
|
||||
* @state: backpointer to global drm_atomic_state
|
||||
*
|
||||
* Note that the distinction between @enable and @active is rather subtile:
|
||||
|
@ -159,6 +157,46 @@ struct drm_crtc_state {
|
|||
struct drm_property_blob *ctm;
|
||||
struct drm_property_blob *gamma_lut;
|
||||
|
||||
/**
|
||||
* @event:
|
||||
*
|
||||
* Optional pointer to a DRM event to signal upon completion of the
|
||||
* state update. The driver must send out the event when the atomic
|
||||
* commit operation completes. There are two cases:
|
||||
*
|
||||
* - The event is for a CRTC which is being disabled through this
|
||||
* atomic commit. In that case the event can be send out any time
|
||||
* after the hardware has stopped scanning out the current
|
||||
* framebuffers. It should contain the timestamp and counter for the
|
||||
* last vblank before the display pipeline was shut off.
|
||||
*
|
||||
* - For a CRTC which is enabled at the end of the commit (even when it
|
||||
* undergoes an full modeset) the vblank timestamp and counter must
|
||||
* be for the vblank right before the first frame that scans out the
|
||||
* new set of buffers. Again the event can only be sent out after the
|
||||
* hardware has stopped scanning out the old buffers.
|
||||
*
|
||||
* - Events for disabled CRTCs are not allowed, and drivers can ignore
|
||||
* that case.
|
||||
*
|
||||
* This can be handled by the drm_crtc_send_vblank_event() function,
|
||||
* which the driver should call on the provided event upon completion of
|
||||
* the atomic commit. Note that if the driver supports vblank signalling
|
||||
* and timestamping the vblank counters and timestamps must agree with
|
||||
* the ones returned from page flip events. With the current vblank
|
||||
* helper infrastructure this can be achieved by holding a vblank
|
||||
* reference while the page flip is pending, acquired through
|
||||
* drm_crtc_vblank_get() and released with drm_crtc_vblank_put().
|
||||
* Drivers are free to implement their own vblank counter and timestamp
|
||||
* tracking though, e.g. if they have accurate timestamp registers in
|
||||
* hardware.
|
||||
*
|
||||
* For hardware which supports some means to synchronize vblank
|
||||
* interrupt delivery with committing display state there's also
|
||||
* drm_crtc_arm_vblank_event(). See the documentation of that function
|
||||
* for a detailed discussion of the constraints it needs to be used
|
||||
* safely.
|
||||
*/
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
struct drm_atomic_state *state;
|
||||
|
@ -835,17 +873,9 @@ struct drm_mode_config_funcs {
|
|||
* CRTC index supplied in &drm_event to userspace.
|
||||
*
|
||||
* The drm core will supply a struct &drm_event in the event
|
||||
* member of each CRTC's &drm_crtc_state structure. This can be handled by the
|
||||
* drm_crtc_send_vblank_event() function, which the driver should call on
|
||||
* the provided event upon completion of the atomic commit. Note that if
|
||||
* the driver supports vblank signalling and timestamping the vblank
|
||||
* counters and timestamps must agree with the ones returned from page
|
||||
* flip events. With the current vblank helper infrastructure this can
|
||||
* be achieved by holding a vblank reference while the page flip is
|
||||
* pending, acquired through drm_crtc_vblank_get() and released with
|
||||
* drm_crtc_vblank_put(). Drivers are free to implement their own vblank
|
||||
* counter and timestamp tracking though, e.g. if they have accurate
|
||||
* timestamp registers in hardware.
|
||||
* member of each CRTC's &drm_crtc_state structure. See the
|
||||
* documentation for &drm_crtc_state for more details about the precise
|
||||
* semantics of this event.
|
||||
*
|
||||
* NOTE:
|
||||
*
|
||||
|
|
|
@ -217,6 +217,19 @@ struct drm_fb_helper {
|
|||
bool delayed_hotplug;
|
||||
};
|
||||
|
||||
/**
|
||||
* @DRM_FB_HELPER_DEFAULT_OPS:
|
||||
*
|
||||
* Helper define to register default implementations of drm_fb_helper
|
||||
* functions. To be used in struct fb_ops of drm drivers.
|
||||
*/
|
||||
#define DRM_FB_HELPER_DEFAULT_OPS \
|
||||
.fb_check_var = drm_fb_helper_check_var, \
|
||||
.fb_set_par = drm_fb_helper_set_par, \
|
||||
.fb_setcmap = drm_fb_helper_setcmap, \
|
||||
.fb_blank = drm_fb_helper_blank, \
|
||||
.fb_pan_display = drm_fb_helper_pan_display
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper,
|
||||
const struct drm_fb_helper_funcs *funcs);
|
||||
|
|
|
@ -396,6 +396,7 @@ header-y += string.h
|
|||
header-y += suspend_ioctls.h
|
||||
header-y += swab.h
|
||||
header-y += synclink.h
|
||||
header-y += sync_file.h
|
||||
header-y += sysctl.h
|
||||
header-y += sysinfo.h
|
||||
header-y += target_core_user.h
|
||||
|
|
Загрузка…
Ссылка в новой задаче