mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 09:59:32 +00:00
Merge tag 'topic/drm-misc-2016-03-14' of git://anongit.freedesktop.org/drm-intel into drm-next
* tag 'topic/drm-misc-2016-03-14' of git://anongit.freedesktop.org/drm-intel: (27 commits) drm: atomic helper: do not unreference error pointer drm/edid: Extract SADs properly from multiple audio data blocks drm: fix blob pointer check drm: introduce pipe color correction properties drm/atomic: Clean up update_connector_routing. drm/atomic: Clean up steal_encoder, v2. drm/atomic: Handle encoder assignment conflicts in a separate check, v3. drm/atomic: Handle encoder stealing from set_config better. drm/atomic: Always call steal_encoder, v2. drm/ast: removed optional dummy crtc mode_fixup function. drm/bochs: removed optional dummy crtc mode_fixup function. drm/fsl-dcu: removed optional dummy crtc mode_fixup function. drm/virtio: removed optional dummy crtc mode_fixup function. drm/nouveau/dispnv04: removed optional dummy crtc mode_fixup function. drm/atmel-hlcdc: remove optional dummy crtc mode_fixup function. drm/sti: removed optional dummy crtc mode_fixup function. drm/shmobile: removed optional dummy crtc mode_fixup function. drm/msm/mdp: removed optional dummy crtc mode_fixup function. drm/omapdrm: removed optional dummy crtc mode_fixup function. drm/rcar-du: removed optional dummy crtc mode_fixup function. ...
This commit is contained in:
commit
1a4be38a3a
31 changed files with 544 additions and 300 deletions
|
@ -1816,7 +1816,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||
<td valign="top" >Description/Restrictions</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="37" valign="top" >DRM</td>
|
||||
<td rowspan="42" valign="top" >DRM</td>
|
||||
<td valign="top" >Generic</td>
|
||||
<td valign="top" >“rotation”</td>
|
||||
<td valign="top" >BITMASK</td>
|
||||
|
@ -2068,7 +2068,7 @@ void intel_crt_init(struct drm_device *dev)
|
|||
<td valign="top" >property to suggest an Y offset for a connector</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="3" valign="top" >Optional</td>
|
||||
<td rowspan="8" valign="top" >Optional</td>
|
||||
<td valign="top" >“scaling mode”</td>
|
||||
<td valign="top" >ENUM</td>
|
||||
<td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td>
|
||||
|
@ -2092,6 +2092,61 @@ void intel_crt_init(struct drm_device *dev)
|
|||
<td valign="top" >TBD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" >“DEGAMMA_LUT”</td>
|
||||
<td valign="top" >BLOB</td>
|
||||
<td valign="top" >0</td>
|
||||
<td valign="top" >CRTC</td>
|
||||
<td valign="top" >DRM property to set the degamma lookup table
|
||||
(LUT) mapping pixel data from the framebuffer before it is
|
||||
given to the transformation matrix. The data is an interpreted
|
||||
as an array of struct drm_color_lut elements. Hardware might
|
||||
choose not to use the full precision of the LUT elements nor
|
||||
use all the elements of the LUT (for example the hardware
|
||||
might choose to interpolate between LUT[0] and LUT[4]). </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" >“DEGAMMA_LUT_SIZE”</td>
|
||||
<td valign="top" >RANGE | IMMUTABLE</td>
|
||||
<td valign="top" >Min=0, Max=UINT_MAX</td>
|
||||
<td valign="top" >CRTC</td>
|
||||
<td valign="top" >DRM property to gives the size of the lookup
|
||||
table to be set on the DEGAMMA_LUT property (the size depends
|
||||
on the underlying hardware).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" >“CTM”</td>
|
||||
<td valign="top" >BLOB</td>
|
||||
<td valign="top" >0</td>
|
||||
<td valign="top" >CRTC</td>
|
||||
<td valign="top" >DRM property to set the current
|
||||
transformation matrix (CTM) apply to pixel data after the
|
||||
lookup through the degamma LUT and before the lookup through
|
||||
the gamma LUT. The data is an interpreted as a struct
|
||||
drm_color_ctm.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" >“GAMMA_LUT”</td>
|
||||
<td valign="top" >BLOB</td>
|
||||
<td valign="top" >0</td>
|
||||
<td valign="top" >CRTC</td>
|
||||
<td valign="top" >DRM property to set the gamma lookup table
|
||||
(LUT) mapping pixel data after to the transformation matrix to
|
||||
data sent to the connector. The data is an interpreted as an
|
||||
array of struct drm_color_lut elements. Hardware might choose
|
||||
not to use the full precision of the LUT elements nor use all
|
||||
the elements of the LUT (for example the hardware might choose
|
||||
to interpolate between LUT[0] and LUT[4]).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" >“GAMMA_LUT_SIZE”</td>
|
||||
<td valign="top" >RANGE | IMMUTABLE</td>
|
||||
<td valign="top" >Min=0, Max=UINT_MAX</td>
|
||||
<td valign="top" >CRTC</td>
|
||||
<td valign="top" >DRM property to gives the size of the lookup
|
||||
table to be set on the GAMMA_LUT property (the size depends on
|
||||
the underlying hardware).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="20" valign="top" >i915</td>
|
||||
<td rowspan="2" valign="top" >Generic</td>
|
||||
<td valign="top" >"Broadcast RGB"</td>
|
||||
|
|
|
@ -497,13 +497,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
}
|
||||
}
|
||||
|
||||
static bool ast_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ast is different - we will force move buffers out of VRAM */
|
||||
static int ast_crtc_do_set_base(struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
|
@ -617,7 +610,6 @@ static void ast_crtc_commit(struct drm_crtc *crtc)
|
|||
|
||||
static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
|
||||
.dpms = ast_crtc_dpms,
|
||||
.mode_fixup = ast_crtc_mode_fixup,
|
||||
.mode_set = ast_crtc_mode_set,
|
||||
.mode_set_base = ast_crtc_mode_set_base,
|
||||
.disable = ast_crtc_disable,
|
||||
|
|
|
@ -121,13 +121,6 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
|
|||
cfg);
|
||||
}
|
||||
|
||||
static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
|
||||
{
|
||||
struct drm_device *dev = c->dev;
|
||||
|
@ -261,7 +254,6 @@ static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = {
|
||||
.mode_fixup = atmel_hlcdc_crtc_mode_fixup,
|
||||
.mode_set = drm_helper_crtc_mode_set,
|
||||
.mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb,
|
||||
.mode_set_base = drm_helper_crtc_mode_set_base,
|
||||
|
@ -349,4 +341,3 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
|
|||
atmel_hlcdc_crtc_destroy(&crtc->base);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,13 +30,6 @@ static void bochs_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
}
|
||||
}
|
||||
|
||||
static bool bochs_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
||||
struct drm_framebuffer *old_fb)
|
||||
{
|
||||
|
@ -135,7 +128,6 @@ static const struct drm_crtc_funcs bochs_crtc_funcs = {
|
|||
|
||||
static const struct drm_crtc_helper_funcs bochs_helper_funcs = {
|
||||
.dpms = bochs_crtc_dpms,
|
||||
.mode_fixup = bochs_crtc_mode_fixup,
|
||||
.mode_set = bochs_crtc_mode_set,
|
||||
.mode_set_base = bochs_crtc_mode_set_base,
|
||||
.prepare = bochs_crtc_prepare,
|
||||
|
|
|
@ -91,18 +91,6 @@ static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
WREG_GFX(0xe, gr0e);
|
||||
}
|
||||
|
||||
/*
|
||||
* The core passes the desired mode to the CRTC code to see whether any
|
||||
* CRTC-specific modifications need to be made to it. We're in a position
|
||||
* to just pass that straight through, so this does nothing
|
||||
*/
|
||||
static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
|
||||
{
|
||||
struct cirrus_device *cdev = crtc->dev->dev_private;
|
||||
|
@ -372,7 +360,6 @@ static const struct drm_crtc_funcs cirrus_crtc_funcs = {
|
|||
|
||||
static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
|
||||
.dpms = cirrus_crtc_dpms,
|
||||
.mode_fixup = cirrus_crtc_mode_fixup,
|
||||
.mode_set = cirrus_crtc_mode_set,
|
||||
.mode_set_base = cirrus_crtc_mode_set_base,
|
||||
.prepare = cirrus_crtc_prepare,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_mode.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
/**
|
||||
|
@ -375,6 +376,59 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
|||
}
|
||||
EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc);
|
||||
|
||||
/**
|
||||
* drm_atomic_replace_property_blob - replace a blob property
|
||||
* @blob: a pointer to the member blob to be replaced
|
||||
* @new_blob: the new blob to replace with
|
||||
* @expected_size: the expected size of the new blob
|
||||
* @replaced: whether the blob has been replaced
|
||||
*
|
||||
* RETURNS:
|
||||
* Zero on success, error code on failure
|
||||
*/
|
||||
static void
|
||||
drm_atomic_replace_property_blob(struct drm_property_blob **blob,
|
||||
struct drm_property_blob *new_blob,
|
||||
bool *replaced)
|
||||
{
|
||||
struct drm_property_blob *old_blob = *blob;
|
||||
|
||||
if (old_blob == new_blob)
|
||||
return;
|
||||
|
||||
if (old_blob)
|
||||
drm_property_unreference_blob(old_blob);
|
||||
if (new_blob)
|
||||
drm_property_reference_blob(new_blob);
|
||||
*blob = new_blob;
|
||||
*replaced = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc,
|
||||
struct drm_property_blob **blob,
|
||||
uint64_t blob_id,
|
||||
ssize_t expected_size,
|
||||
bool *replaced)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_property_blob *new_blob = NULL;
|
||||
|
||||
if (blob_id != 0) {
|
||||
new_blob = drm_property_lookup_blob(dev, blob_id);
|
||||
if (new_blob == NULL)
|
||||
return -EINVAL;
|
||||
if (expected_size > 0 && expected_size != new_blob->length)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
drm_atomic_replace_property_blob(blob, new_blob, replaced);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_crtc_set_property - set property on CRTC
|
||||
* @crtc: the drm CRTC to set a property on
|
||||
|
@ -397,6 +451,7 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
|
|||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
bool replaced = false;
|
||||
int ret;
|
||||
|
||||
if (property == config->prop_active)
|
||||
|
@ -407,8 +462,31 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
|
|||
ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
|
||||
drm_property_unreference_blob(mode);
|
||||
return ret;
|
||||
}
|
||||
else if (crtc->funcs->atomic_set_property)
|
||||
} else if (property == config->degamma_lut_property) {
|
||||
ret = drm_atomic_replace_property_blob_from_id(crtc,
|
||||
&state->degamma_lut,
|
||||
val,
|
||||
-1,
|
||||
&replaced);
|
||||
state->color_mgmt_changed = replaced;
|
||||
return ret;
|
||||
} else if (property == config->ctm_property) {
|
||||
ret = drm_atomic_replace_property_blob_from_id(crtc,
|
||||
&state->ctm,
|
||||
val,
|
||||
sizeof(struct drm_color_ctm),
|
||||
&replaced);
|
||||
state->color_mgmt_changed = replaced;
|
||||
return ret;
|
||||
} else if (property == config->gamma_lut_property) {
|
||||
ret = drm_atomic_replace_property_blob_from_id(crtc,
|
||||
&state->gamma_lut,
|
||||
val,
|
||||
-1,
|
||||
&replaced);
|
||||
state->color_mgmt_changed = replaced;
|
||||
return ret;
|
||||
} else if (crtc->funcs->atomic_set_property)
|
||||
return crtc->funcs->atomic_set_property(crtc, state, property, val);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
@ -444,6 +522,12 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc,
|
|||
*val = state->active;
|
||||
else if (property == config->prop_mode_id)
|
||||
*val = (state->mode_blob) ? state->mode_blob->base.id : 0;
|
||||
else if (property == config->degamma_lut_property)
|
||||
*val = (state->degamma_lut) ? state->degamma_lut->base.id : 0;
|
||||
else if (property == config->ctm_property)
|
||||
*val = (state->ctm) ? state->ctm->base.id : 0;
|
||||
else if (property == config->gamma_lut_property)
|
||||
*val = (state->gamma_lut) ? state->gamma_lut->base.id : 0;
|
||||
else if (crtc->funcs->atomic_get_property)
|
||||
return crtc->funcs->atomic_get_property(crtc, state, property, val);
|
||||
else
|
||||
|
|
|
@ -86,43 +86,104 @@ drm_atomic_helper_plane_changed(struct drm_atomic_state *state,
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
check_pending_encoder_assignment(struct drm_atomic_state *state,
|
||||
struct drm_encoder *new_encoder)
|
||||
static int handle_conflicting_encoders(struct drm_atomic_state *state,
|
||||
bool disable_conflicting_encoders)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
int i;
|
||||
|
||||
for_each_connector_in_state(state, connector, conn_state, i) {
|
||||
if (conn_state->best_encoder != new_encoder)
|
||||
continue;
|
||||
|
||||
/* encoder already assigned and we're trying to re-steal it! */
|
||||
if (connector->state->best_encoder != conn_state->best_encoder)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct drm_crtc *
|
||||
get_current_crtc_for_encoder(struct drm_device *dev,
|
||||
struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
unsigned encoder_mask = 0;
|
||||
int i, ret;
|
||||
|
||||
WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
|
||||
/*
|
||||
* First loop, find all newly assigned encoders from the connectors
|
||||
* part of the state. If the same encoder is assigned to multiple
|
||||
* connectors bail out.
|
||||
*/
|
||||
for_each_connector_in_state(state, connector, conn_state, i) {
|
||||
const struct drm_connector_helper_funcs *funcs = connector->helper_private;
|
||||
struct drm_encoder *new_encoder;
|
||||
|
||||
drm_for_each_connector(connector, dev) {
|
||||
if (connector->state->best_encoder != encoder)
|
||||
if (!conn_state->crtc)
|
||||
continue;
|
||||
|
||||
return connector->state->crtc;
|
||||
if (funcs->atomic_best_encoder)
|
||||
new_encoder = funcs->atomic_best_encoder(connector, conn_state);
|
||||
else
|
||||
new_encoder = funcs->best_encoder(connector);
|
||||
|
||||
if (new_encoder) {
|
||||
if (encoder_mask & (1 << drm_encoder_index(new_encoder))) {
|
||||
DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] on [CONNECTOR:%d:%s] already assigned\n",
|
||||
new_encoder->base.id, new_encoder->name,
|
||||
connector->base.id, connector->name);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
encoder_mask |= 1 << drm_encoder_index(new_encoder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!encoder_mask)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Second loop, iterate over all connectors not part of the state.
|
||||
*
|
||||
* If a conflicting encoder is found and disable_conflicting_encoders
|
||||
* is not set, an error is returned. Userspace can provide a solution
|
||||
* through the atomic ioctl.
|
||||
*
|
||||
* If the flag is set conflicting connectors are removed from the crtc
|
||||
* and the crtc is disabled if no encoder is left. This preserves
|
||||
* compatibility with the legacy set_config behavior.
|
||||
*/
|
||||
drm_for_each_connector(connector, state->dev) {
|
||||
struct drm_crtc_state *crtc_state;
|
||||
|
||||
if (drm_atomic_get_existing_connector_state(state, connector))
|
||||
continue;
|
||||
|
||||
encoder = connector->state->best_encoder;
|
||||
if (!encoder || !(encoder_mask & (1 << drm_encoder_index(encoder))))
|
||||
continue;
|
||||
|
||||
if (!disable_conflicting_encoders) {
|
||||
DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s] by [CONNECTOR:%d:%s]\n",
|
||||
encoder->base.id, encoder->name,
|
||||
connector->state->crtc->base.id,
|
||||
connector->state->crtc->name,
|
||||
connector->base.id, connector->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
conn_state = drm_atomic_get_connector_state(state, connector);
|
||||
if (IS_ERR(conn_state))
|
||||
return PTR_ERR(conn_state);
|
||||
|
||||
DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n",
|
||||
encoder->base.id, encoder->name,
|
||||
conn_state->crtc->base.id, conn_state->crtc->name,
|
||||
connector->base.id, connector->name);
|
||||
|
||||
crtc_state = drm_atomic_get_existing_crtc_state(state, conn_state->crtc);
|
||||
|
||||
ret = drm_atomic_set_crtc_for_connector(conn_state, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!crtc_state->connector_mask) {
|
||||
ret = drm_atomic_set_mode_prop_for_crtc(crtc_state,
|
||||
NULL);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
crtc_state->active = false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -166,70 +227,44 @@ set_best_encoder(struct drm_atomic_state *state,
|
|||
conn_state->best_encoder = encoder;
|
||||
}
|
||||
|
||||
static int
|
||||
static void
|
||||
steal_encoder(struct drm_atomic_state *state,
|
||||
struct drm_encoder *encoder,
|
||||
struct drm_crtc *encoder_crtc)
|
||||
struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_mode_config *config = &state->dev->mode_config;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *connector_state;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We can only steal an encoder coming from a connector, which means we
|
||||
* must already hold the connection_mutex.
|
||||
*/
|
||||
WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
|
||||
for_each_connector_in_state(state, connector, connector_state, i) {
|
||||
struct drm_crtc *encoder_crtc;
|
||||
|
||||
if (connector_state->best_encoder != encoder)
|
||||
continue;
|
||||
|
||||
encoder_crtc = connector->state->crtc;
|
||||
|
||||
DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n",
|
||||
encoder->base.id, encoder->name,
|
||||
encoder_crtc->base.id, encoder_crtc->name);
|
||||
|
||||
crtc_state = drm_atomic_get_crtc_state(state, encoder_crtc);
|
||||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
set_best_encoder(state, connector_state, NULL);
|
||||
|
||||
crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc);
|
||||
crtc_state->connectors_changed = true;
|
||||
|
||||
list_for_each_entry(connector, &config->connector_list, head) {
|
||||
if (connector->state->best_encoder != encoder)
|
||||
continue;
|
||||
|
||||
DRM_DEBUG_ATOMIC("Stealing encoder from [CONNECTOR:%d:%s]\n",
|
||||
connector->base.id,
|
||||
connector->name);
|
||||
|
||||
connector_state = drm_atomic_get_connector_state(state,
|
||||
connector);
|
||||
if (IS_ERR(connector_state))
|
||||
return PTR_ERR(connector_state);
|
||||
|
||||
if (connector_state->best_encoder != encoder)
|
||||
continue;
|
||||
|
||||
set_best_encoder(state, connector_state, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
update_connector_routing(struct drm_atomic_state *state, int conn_idx)
|
||||
update_connector_routing(struct drm_atomic_state *state,
|
||||
struct drm_connector *connector,
|
||||
struct drm_connector_state *connector_state)
|
||||
{
|
||||
const struct drm_connector_helper_funcs *funcs;
|
||||
struct drm_encoder *new_encoder;
|
||||
struct drm_crtc *encoder_crtc;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *connector_state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
int idx, ret;
|
||||
|
||||
connector = state->connectors[conn_idx];
|
||||
connector_state = state->connector_states[conn_idx];
|
||||
|
||||
if (!connector)
|
||||
return 0;
|
||||
|
||||
DRM_DEBUG_ATOMIC("Updating routing for [CONNECTOR:%d:%s]\n",
|
||||
connector->base.id,
|
||||
|
@ -237,16 +272,12 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
|
|||
|
||||
if (connector->state->crtc != connector_state->crtc) {
|
||||
if (connector->state->crtc) {
|
||||
idx = drm_crtc_index(connector->state->crtc);
|
||||
|
||||
crtc_state = state->crtc_states[idx];
|
||||
crtc_state = drm_atomic_get_existing_crtc_state(state, connector->state->crtc);
|
||||
crtc_state->connectors_changed = true;
|
||||
}
|
||||
|
||||
if (connector_state->crtc) {
|
||||
idx = drm_crtc_index(connector_state->crtc);
|
||||
|
||||
crtc_state = state->crtc_states[idx];
|
||||
crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc);
|
||||
crtc_state->connectors_changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -298,34 +329,11 @@ update_connector_routing(struct drm_atomic_state *state, int conn_idx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!check_pending_encoder_assignment(state, new_encoder)) {
|
||||
DRM_DEBUG_ATOMIC("Encoder for [CONNECTOR:%d:%s] already assigned\n",
|
||||
connector->base.id,
|
||||
connector->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
encoder_crtc = get_current_crtc_for_encoder(state->dev,
|
||||
new_encoder);
|
||||
|
||||
if (encoder_crtc) {
|
||||
ret = steal_encoder(state, new_encoder, encoder_crtc);
|
||||
if (ret) {
|
||||
DRM_DEBUG_ATOMIC("Encoder stealing failed for [CONNECTOR:%d:%s]\n",
|
||||
connector->base.id,
|
||||
connector->name);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ON(!connector_state->crtc))
|
||||
return -EINVAL;
|
||||
steal_encoder(state, new_encoder);
|
||||
|
||||
set_best_encoder(state, connector_state, new_encoder);
|
||||
|
||||
idx = drm_crtc_index(connector_state->crtc);
|
||||
|
||||
crtc_state = state->crtc_states[idx];
|
||||
crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc);
|
||||
crtc_state->connectors_changed = true;
|
||||
|
||||
DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n",
|
||||
|
@ -488,13 +496,18 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
|
|||
}
|
||||
}
|
||||
|
||||
ret = handle_conflicting_encoders(state, state->legacy_set_config);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for_each_connector_in_state(state, connector, connector_state, i) {
|
||||
/*
|
||||
* This only sets crtc->mode_changed for routing changes,
|
||||
* drivers must set crtc->mode_changed themselves when connector
|
||||
* properties need to be updated.
|
||||
*/
|
||||
ret = update_connector_routing(state, i);
|
||||
ret = update_connector_routing(state, connector,
|
||||
connector_state);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -1761,28 +1774,18 @@ static int update_output_state(struct drm_atomic_state *state,
|
|||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_connector *connector;
|
||||
struct drm_connector_state *conn_state;
|
||||
int ret, i, j;
|
||||
int ret, i;
|
||||
|
||||
ret = drm_modeset_lock(&dev->mode_config.connection_mutex,
|
||||
state->acquire_ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* First grab all affected connector/crtc states. */
|
||||
for (i = 0; i < set->num_connectors; i++) {
|
||||
conn_state = drm_atomic_get_connector_state(state,
|
||||
set->connectors[i]);
|
||||
if (IS_ERR(conn_state))
|
||||
return PTR_ERR(conn_state);
|
||||
}
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
ret = drm_atomic_add_affected_connectors(state, crtc);
|
||||
/* First disable all connectors on the target crtc. */
|
||||
ret = drm_atomic_add_affected_connectors(state, set->crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Then recompute connector->crtc links and crtc enabling state. */
|
||||
for_each_connector_in_state(state, connector, conn_state, i) {
|
||||
if (conn_state->crtc == set->crtc) {
|
||||
ret = drm_atomic_set_crtc_for_connector(conn_state,
|
||||
|
@ -1790,16 +1793,19 @@ static int update_output_state(struct drm_atomic_state *state,
|
|||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Then set all connectors from set->connectors on the target crtc */
|
||||
for (i = 0; i < set->num_connectors; i++) {
|
||||
conn_state = drm_atomic_get_connector_state(state,
|
||||
set->connectors[i]);
|
||||
if (IS_ERR(conn_state))
|
||||
return PTR_ERR(conn_state);
|
||||
|
||||
for (j = 0; j < set->num_connectors; j++) {
|
||||
if (set->connectors[j] == connector) {
|
||||
ret = drm_atomic_set_crtc_for_connector(conn_state,
|
||||
set->crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for_each_crtc_in_state(state, crtc, crtc_state, i) {
|
||||
|
@ -1842,6 +1848,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
|
|||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
state->legacy_set_config = true;
|
||||
state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc);
|
||||
retry:
|
||||
ret = __drm_atomic_helper_set_config(set, state);
|
||||
|
@ -2488,8 +2495,12 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_dpms);
|
|||
*/
|
||||
void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc)
|
||||
{
|
||||
if (crtc->state)
|
||||
if (crtc->state) {
|
||||
drm_property_unreference_blob(crtc->state->mode_blob);
|
||||
drm_property_unreference_blob(crtc->state->degamma_lut);
|
||||
drm_property_unreference_blob(crtc->state->ctm);
|
||||
drm_property_unreference_blob(crtc->state->gamma_lut);
|
||||
}
|
||||
kfree(crtc->state);
|
||||
crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL);
|
||||
|
||||
|
@ -2513,10 +2524,17 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc,
|
|||
|
||||
if (state->mode_blob)
|
||||
drm_property_reference_blob(state->mode_blob);
|
||||
if (state->degamma_lut)
|
||||
drm_property_reference_blob(state->degamma_lut);
|
||||
if (state->ctm)
|
||||
drm_property_reference_blob(state->ctm);
|
||||
if (state->gamma_lut)
|
||||
drm_property_reference_blob(state->gamma_lut);
|
||||
state->mode_changed = false;
|
||||
state->active_changed = false;
|
||||
state->planes_changed = false;
|
||||
state->connectors_changed = false;
|
||||
state->color_mgmt_changed = false;
|
||||
state->event = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state);
|
||||
|
@ -2557,6 +2575,9 @@ void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc,
|
|||
struct drm_crtc_state *state)
|
||||
{
|
||||
drm_property_unreference_blob(state->mode_blob);
|
||||
drm_property_unreference_blob(state->degamma_lut);
|
||||
drm_property_unreference_blob(state->ctm);
|
||||
drm_property_unreference_blob(state->gamma_lut);
|
||||
}
|
||||
EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state);
|
||||
|
||||
|
@ -2870,3 +2891,98 @@ void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
|||
kfree(state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state);
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table
|
||||
* @crtc: CRTC object
|
||||
* @red: red correction table
|
||||
* @green: green correction table
|
||||
* @blue: green correction table
|
||||
* @start:
|
||||
* @size: size of the tables
|
||||
*
|
||||
* Implements support for legacy gamma correction table for drivers
|
||||
* that support color management through the DEGAMMA_LUT/GAMMA_LUT
|
||||
* properties.
|
||||
*/
|
||||
void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
|
||||
u16 *red, u16 *green, u16 *blue,
|
||||
uint32_t start, uint32_t size)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_property_blob *blob = NULL;
|
||||
struct drm_color_lut *blob_data;
|
||||
int i, ret = 0;
|
||||
|
||||
state = drm_atomic_state_alloc(crtc->dev);
|
||||
if (!state)
|
||||
return;
|
||||
|
||||
blob = drm_property_create_blob(dev,
|
||||
sizeof(struct drm_color_lut) * size,
|
||||
NULL);
|
||||
if (IS_ERR(blob)) {
|
||||
ret = PTR_ERR(blob);
|
||||
blob = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Prepare GAMMA_LUT with the legacy values. */
|
||||
blob_data = (struct drm_color_lut *) blob->data;
|
||||
for (i = 0; i < size; i++) {
|
||||
blob_data[i].red = red[i];
|
||||
blob_data[i].green = green[i];
|
||||
blob_data[i].blue = blue[i];
|
||||
}
|
||||
|
||||
state->acquire_ctx = crtc->dev->mode_config.acquire_ctx;
|
||||
retry:
|
||||
crtc_state = drm_atomic_get_crtc_state(state, crtc);
|
||||
if (IS_ERR(crtc_state)) {
|
||||
ret = PTR_ERR(crtc_state);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Reset DEGAMMA_LUT and CTM properties. */
|
||||
ret = drm_atomic_crtc_set_property(crtc, crtc_state,
|
||||
config->degamma_lut_property, 0);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = drm_atomic_crtc_set_property(crtc, crtc_state,
|
||||
config->ctm_property, 0);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = drm_atomic_crtc_set_property(crtc, crtc_state,
|
||||
config->gamma_lut_property, blob->base.id);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
/* Driver takes ownership of state on successful commit. */
|
||||
|
||||
drm_property_unreference_blob(blob);
|
||||
|
||||
return;
|
||||
fail:
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
||||
drm_atomic_state_free(state);
|
||||
drm_property_unreference_blob(blob);
|
||||
|
||||
return;
|
||||
backoff:
|
||||
drm_atomic_state_clear(state);
|
||||
drm_atomic_legacy_backoff(state);
|
||||
|
||||
goto retry;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
|
||||
|
|
|
@ -430,9 +430,7 @@ EXPORT_SYMBOL(drm_framebuffer_init);
|
|||
static void __drm_framebuffer_unregister(struct drm_device *dev,
|
||||
struct drm_framebuffer *fb)
|
||||
{
|
||||
mutex_lock(&dev->mode_config.idr_mutex);
|
||||
idr_remove(&dev->mode_config.crtc_idr, fb->base.id);
|
||||
mutex_unlock(&dev->mode_config.idr_mutex);
|
||||
drm_mode_object_put(dev, &fb->base);
|
||||
|
||||
fb->base.id = 0;
|
||||
}
|
||||
|
@ -1554,6 +1552,41 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
|
|||
return -ENOMEM;
|
||||
dev->mode_config.prop_mode_id = prop;
|
||||
|
||||
prop = drm_property_create(dev,
|
||||
DRM_MODE_PROP_BLOB,
|
||||
"DEGAMMA_LUT", 0);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
dev->mode_config.degamma_lut_property = prop;
|
||||
|
||||
prop = drm_property_create_range(dev,
|
||||
DRM_MODE_PROP_IMMUTABLE,
|
||||
"DEGAMMA_LUT_SIZE", 0, UINT_MAX);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
dev->mode_config.degamma_lut_size_property = prop;
|
||||
|
||||
prop = drm_property_create(dev,
|
||||
DRM_MODE_PROP_BLOB,
|
||||
"CTM", 0);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
dev->mode_config.ctm_property = prop;
|
||||
|
||||
prop = drm_property_create(dev,
|
||||
DRM_MODE_PROP_BLOB,
|
||||
"GAMMA_LUT", 0);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
dev->mode_config.gamma_lut_property = prop;
|
||||
|
||||
prop = drm_property_create_range(dev,
|
||||
DRM_MODE_PROP_IMMUTABLE,
|
||||
"GAMMA_LUT_SIZE", 0, UINT_MAX);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
dev->mode_config.gamma_lut_size_property = prop;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1075,3 +1075,36 @@ int drm_helper_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
return drm_plane_helper_commit(plane, plane_state, old_fb);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_crtc_mode_set_base);
|
||||
|
||||
/**
|
||||
* drm_helper_crtc_enable_color_mgmt - enable color management properties
|
||||
* @crtc: DRM CRTC
|
||||
* @degamma_lut_size: the size of the degamma lut (before CSC)
|
||||
* @gamma_lut_size: the size of the gamma lut (after CSC)
|
||||
*
|
||||
* This function lets the driver enable the color correction properties on a
|
||||
* CRTC. This includes 3 degamma, csc and gamma properties that userspace can
|
||||
* set and 2 size properties to inform the userspace of the lut sizes.
|
||||
*/
|
||||
void drm_helper_crtc_enable_color_mgmt(struct drm_crtc *crtc,
|
||||
int degamma_lut_size,
|
||||
int gamma_lut_size)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
|
||||
drm_object_attach_property(&crtc->base,
|
||||
config->degamma_lut_property, 0);
|
||||
drm_object_attach_property(&crtc->base,
|
||||
config->ctm_property, 0);
|
||||
drm_object_attach_property(&crtc->base,
|
||||
config->gamma_lut_property, 0);
|
||||
|
||||
drm_object_attach_property(&crtc->base,
|
||||
config->degamma_lut_size_property,
|
||||
degamma_lut_size);
|
||||
drm_object_attach_property(&crtc->base,
|
||||
config->gamma_lut_size_property,
|
||||
gamma_lut_size);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_helper_crtc_enable_color_mgmt);
|
||||
|
|
|
@ -3308,7 +3308,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
|||
u8 *cea;
|
||||
u8 *name;
|
||||
u8 *db;
|
||||
int sad_count = 0;
|
||||
int total_sad_count = 0;
|
||||
int mnl;
|
||||
int dbl;
|
||||
|
||||
|
@ -3322,6 +3322,7 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
|||
|
||||
name = NULL;
|
||||
drm_for_each_detailed_block((u8 *)edid, monitor_name, &name);
|
||||
/* max: 13 bytes EDID, 16 bytes ELD */
|
||||
for (mnl = 0; name && mnl < 13; mnl++) {
|
||||
if (name[mnl] == 0x0a)
|
||||
break;
|
||||
|
@ -3350,11 +3351,15 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
|||
dbl = cea_db_payload_len(db);
|
||||
|
||||
switch (cea_db_tag(db)) {
|
||||
int sad_count;
|
||||
|
||||
case AUDIO_BLOCK:
|
||||
/* Audio Data Block, contains SADs */
|
||||
sad_count = dbl / 3;
|
||||
if (dbl >= 1)
|
||||
memcpy(eld + 20 + mnl, &db[1], dbl);
|
||||
sad_count = min(dbl / 3, 15 - total_sad_count);
|
||||
if (sad_count >= 1)
|
||||
memcpy(eld + 20 + mnl + total_sad_count * 3,
|
||||
&db[1], sad_count * 3);
|
||||
total_sad_count += sad_count;
|
||||
break;
|
||||
case SPEAKER_BLOCK:
|
||||
/* Speaker Allocation Data Block */
|
||||
|
@ -3371,13 +3376,13 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid)
|
|||
}
|
||||
}
|
||||
}
|
||||
eld[5] |= sad_count << 4;
|
||||
eld[5] |= total_sad_count << 4;
|
||||
|
||||
eld[DRM_ELD_BASELINE_ELD_LEN] =
|
||||
DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4);
|
||||
|
||||
DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
|
||||
drm_eld_size(eld), sad_count);
|
||||
drm_eld_size(eld), total_sad_count);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_edid_to_eld);
|
||||
|
||||
|
|
|
@ -62,13 +62,6 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc)
|
|||
DCU_UPDATE_MODE_READREG);
|
||||
}
|
||||
|
||||
static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -127,7 +120,6 @@ static const struct drm_crtc_helper_funcs fsl_dcu_drm_crtc_helper_funcs = {
|
|||
.atomic_flush = fsl_dcu_drm_crtc_atomic_flush,
|
||||
.disable = fsl_dcu_drm_disable_crtc,
|
||||
.enable = fsl_dcu_drm_crtc_enable,
|
||||
.mode_fixup = fsl_dcu_drm_crtc_mode_fixup,
|
||||
.mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb,
|
||||
};
|
||||
|
||||
|
|
|
@ -974,7 +974,6 @@ struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
|
|||
|
||||
const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
|
||||
.dpms = gma_crtc_dpms,
|
||||
.mode_fixup = gma_crtc_mode_fixup,
|
||||
.mode_set = cdv_intel_crtc_mode_set,
|
||||
.mode_set_base = gma_pipe_set_base,
|
||||
.prepare = gma_crtc_prepare,
|
||||
|
|
|
@ -478,13 +478,6 @@ int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool gma_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void gma_crtc_prepare(struct drm_crtc *crtc)
|
||||
{
|
||||
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
|
|
@ -75,9 +75,6 @@ extern void gma_crtc_load_lut(struct drm_crtc *crtc);
|
|||
extern void gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
|
||||
u16 *blue, u32 start, u32 size);
|
||||
extern void gma_crtc_dpms(struct drm_crtc *crtc, int mode);
|
||||
extern bool gma_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode);
|
||||
extern void gma_crtc_prepare(struct drm_crtc *crtc);
|
||||
extern void gma_crtc_commit(struct drm_crtc *crtc);
|
||||
extern void gma_crtc_disable(struct drm_crtc *crtc);
|
||||
|
|
|
@ -1026,10 +1026,8 @@ static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
|
|||
|
||||
const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
|
||||
.dpms = mdfld_crtc_dpms,
|
||||
.mode_fixup = gma_crtc_mode_fixup,
|
||||
.mode_set = mdfld_crtc_mode_set,
|
||||
.mode_set_base = mdfld__intel_pipe_set_base,
|
||||
.prepare = gma_crtc_prepare,
|
||||
.commit = gma_crtc_commit,
|
||||
};
|
||||
|
||||
|
|
|
@ -657,7 +657,6 @@ static int oaktrail_pipe_set_base(struct drm_crtc *crtc,
|
|||
|
||||
const struct drm_crtc_helper_funcs oaktrail_helper_funcs = {
|
||||
.dpms = oaktrail_crtc_dpms,
|
||||
.mode_fixup = gma_crtc_mode_fixup,
|
||||
.mode_set = oaktrail_crtc_mode_set,
|
||||
.mode_set_base = oaktrail_pipe_set_base,
|
||||
.prepare = gma_crtc_prepare,
|
||||
|
|
|
@ -430,7 +430,6 @@ struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
|
|||
|
||||
const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
|
||||
.dpms = gma_crtc_dpms,
|
||||
.mode_fixup = gma_crtc_mode_fixup,
|
||||
.mode_set = psb_intel_crtc_mode_set,
|
||||
.mode_set_base = gma_pipe_set_base,
|
||||
.prepare = gma_crtc_prepare,
|
||||
|
|
|
@ -92,18 +92,6 @@ static inline void mga_wait_busy(struct mga_device *mdev)
|
|||
} while ((status & 0x01) && time_before(jiffies, timeout));
|
||||
}
|
||||
|
||||
/*
|
||||
* The core passes the desired mode to the CRTC code to see whether any
|
||||
* CRTC-specific modifications need to be made to it. We're in a position
|
||||
* to just pass that straight through, so this does nothing
|
||||
*/
|
||||
static bool mga_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#define P_ARRAY_SIZE 9
|
||||
|
||||
static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
|
||||
|
@ -1410,7 +1398,6 @@ static const struct drm_crtc_funcs mga_crtc_funcs = {
|
|||
static const struct drm_crtc_helper_funcs mga_helper_funcs = {
|
||||
.disable = mga_crtc_disable,
|
||||
.dpms = mga_crtc_dpms,
|
||||
.mode_fixup = mga_crtc_mode_fixup,
|
||||
.mode_set = mga_crtc_mode_set,
|
||||
.mode_set_base = mga_crtc_mode_set_base,
|
||||
.prepare = mga_crtc_prepare,
|
||||
|
|
|
@ -147,13 +147,6 @@ static void mdp4_crtc_destroy(struct drm_crtc *crtc)
|
|||
kfree(mdp4_crtc);
|
||||
}
|
||||
|
||||
static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/* statically (for now) map planes to mixer stage (z-order): */
|
||||
static const int idxs[] = {
|
||||
[VG1] = 1,
|
||||
|
@ -501,7 +494,6 @@ static const struct drm_crtc_funcs mdp4_crtc_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = {
|
||||
.mode_fixup = mdp4_crtc_mode_fixup,
|
||||
.mode_set_nofb = mdp4_crtc_mode_set_nofb,
|
||||
.disable = mdp4_crtc_disable,
|
||||
.enable = mdp4_crtc_enable,
|
||||
|
|
|
@ -185,13 +185,6 @@ static void mdp5_crtc_destroy(struct drm_crtc *crtc)
|
|||
kfree(mdp5_crtc);
|
||||
}
|
||||
|
||||
static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* blend_setup() - blend all the planes of a CRTC
|
||||
*
|
||||
|
@ -627,7 +620,6 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = {
|
||||
.mode_fixup = mdp5_crtc_mode_fixup,
|
||||
.mode_set_nofb = mdp5_crtc_mode_set_nofb,
|
||||
.disable = mdp5_crtc_disable,
|
||||
.enable = mdp5_crtc_enable,
|
||||
|
|
|
@ -227,13 +227,6 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
|
||||
}
|
||||
|
||||
static bool
|
||||
nv_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
{
|
||||
|
@ -1093,7 +1086,6 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = {
|
|||
.dpms = nv_crtc_dpms,
|
||||
.prepare = nv_crtc_prepare,
|
||||
.commit = nv_crtc_commit,
|
||||
.mode_fixup = nv_crtc_mode_fixup,
|
||||
.mode_set = nv_crtc_mode_set,
|
||||
.mode_set_base = nv04_crtc_mode_set_base,
|
||||
.mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
|
||||
|
|
|
@ -332,13 +332,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc)
|
|||
kfree(omap_crtc);
|
||||
}
|
||||
|
||||
static bool omap_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void omap_crtc_enable(struct drm_crtc *crtc)
|
||||
{
|
||||
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
|
||||
|
@ -475,7 +468,6 @@ static const struct drm_crtc_funcs omap_crtc_funcs = {
|
|||
};
|
||||
|
||||
static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = {
|
||||
.mode_fixup = omap_crtc_mode_fixup,
|
||||
.mode_set_nofb = omap_crtc_mode_set_nofb,
|
||||
.disable = omap_crtc_disable,
|
||||
.enable = omap_crtc_enable,
|
||||
|
|
|
@ -491,14 +491,6 @@ static void rcar_du_crtc_disable(struct drm_crtc *crtc)
|
|||
rcrtc->outputs = 0;
|
||||
}
|
||||
|
||||
static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
/* TODO Fixup modes */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *old_crtc_state)
|
||||
{
|
||||
|
@ -531,7 +523,6 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
}
|
||||
|
||||
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
|
||||
.mode_fixup = rcar_du_crtc_mode_fixup,
|
||||
.disable = rcar_du_crtc_disable,
|
||||
.enable = rcar_du_crtc_enable,
|
||||
.atomic_begin = rcar_du_crtc_atomic_begin,
|
||||
|
|
|
@ -359,13 +359,6 @@ static void shmob_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
scrtc->dpms = mode;
|
||||
}
|
||||
|
||||
static bool shmob_drm_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void shmob_drm_crtc_mode_prepare(struct drm_crtc *crtc)
|
||||
{
|
||||
shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
|
||||
|
@ -431,7 +424,6 @@ static int shmob_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
|
|||
|
||||
static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
|
||||
.dpms = shmob_drm_crtc_dpms,
|
||||
.mode_fixup = shmob_drm_crtc_mode_fixup,
|
||||
.prepare = shmob_drm_crtc_mode_prepare,
|
||||
.commit = shmob_drm_crtc_mode_commit,
|
||||
.mode_set = shmob_drm_crtc_mode_set,
|
||||
|
|
|
@ -51,14 +51,6 @@ static void sti_crtc_disabling(struct drm_crtc *crtc)
|
|||
mixer->status = STI_MIXER_DISABLING;
|
||||
}
|
||||
|
||||
static bool sti_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
/* accept the provided drm_display_mode, do not fix it up */
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode)
|
||||
{
|
||||
|
@ -229,7 +221,6 @@ static void sti_crtc_atomic_flush(struct drm_crtc *crtc,
|
|||
static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = {
|
||||
.enable = sti_crtc_enable,
|
||||
.disable = sti_crtc_disabling,
|
||||
.mode_fixup = sti_crtc_mode_fixup,
|
||||
.mode_set = drm_helper_crtc_mode_set,
|
||||
.mode_set_nofb = sti_crtc_mode_set_nofb,
|
||||
.mode_set_base = drm_helper_crtc_mode_set_base,
|
||||
|
|
|
@ -279,14 +279,6 @@ static void udl_crtc_dpms(struct drm_crtc *crtc, int mode)
|
|||
|
||||
}
|
||||
|
||||
static bool udl_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
udl_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
|
||||
|
@ -402,7 +394,6 @@ static void udl_crtc_commit(struct drm_crtc *crtc)
|
|||
|
||||
static const struct drm_crtc_helper_funcs udl_helper_funcs = {
|
||||
.dpms = udl_crtc_dpms,
|
||||
.mode_fixup = udl_crtc_mode_fixup,
|
||||
.mode_set = udl_crtc_mode_set,
|
||||
.prepare = udl_crtc_prepare,
|
||||
.commit = udl_crtc_commit,
|
||||
|
|
|
@ -237,13 +237,6 @@ virtio_gpu_framebuffer_init(struct drm_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool virtio_gpu_crtc_mode_fixup(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -277,7 +270,6 @@ static int virtio_gpu_crtc_atomic_check(struct drm_crtc *crtc,
|
|||
static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = {
|
||||
.enable = virtio_gpu_crtc_enable,
|
||||
.disable = virtio_gpu_crtc_disable,
|
||||
.mode_fixup = virtio_gpu_crtc_mode_fixup,
|
||||
.mode_set_nofb = virtio_gpu_crtc_mode_set_nofb,
|
||||
.atomic_check = virtio_gpu_crtc_atomic_check,
|
||||
};
|
||||
|
|
|
@ -146,6 +146,9 @@ __drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
|||
struct drm_connector_state *state);
|
||||
void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector,
|
||||
struct drm_connector_state *state);
|
||||
void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc,
|
||||
u16 *red, u16 *green, u16 *blue,
|
||||
uint32_t start, uint32_t size);
|
||||
|
||||
/**
|
||||
* drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
|
||||
|
|
|
@ -305,6 +305,8 @@ struct drm_plane_helper_funcs;
|
|||
* @mode_changed: crtc_state->mode or crtc_state->enable has been changed
|
||||
* @active_changed: crtc_state->active has been toggled.
|
||||
* @connectors_changed: connectors to this crtc have been updated
|
||||
* @color_mgmt_changed: color management properties have changed (degamma or
|
||||
* gamma LUT or CSC matrix)
|
||||
* @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes
|
||||
* @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors
|
||||
* @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders
|
||||
|
@ -312,6 +314,11 @@ struct drm_plane_helper_funcs;
|
|||
* update to ensure framebuffer cleanup isn't done too early
|
||||
* @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings
|
||||
* @mode: current mode timings
|
||||
* @degamma_lut: Lookup table for converting framebuffer pixel data
|
||||
* before apply the conversion matrix
|
||||
* @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
|
||||
|
@ -333,6 +340,7 @@ struct drm_crtc_state {
|
|||
bool mode_changed : 1;
|
||||
bool active_changed : 1;
|
||||
bool connectors_changed : 1;
|
||||
bool color_mgmt_changed : 1;
|
||||
|
||||
/* attached planes bitmask:
|
||||
* WARNING: transitional helpers do not maintain plane_mask so
|
||||
|
@ -355,6 +363,11 @@ struct drm_crtc_state {
|
|||
/* blob property to expose current mode to atomic userspace */
|
||||
struct drm_property_blob *mode_blob;
|
||||
|
||||
/* blob property to expose color management to userspace */
|
||||
struct drm_property_blob *degamma_lut;
|
||||
struct drm_property_blob *ctm;
|
||||
struct drm_property_blob *gamma_lut;
|
||||
|
||||
struct drm_pending_vblank_event *event;
|
||||
|
||||
struct drm_atomic_state *state;
|
||||
|
@ -757,7 +770,7 @@ struct drm_crtc {
|
|||
int x, y;
|
||||
const struct drm_crtc_funcs *funcs;
|
||||
|
||||
/* CRTC gamma size for reporting to userspace */
|
||||
/* Legacy FB CRTC gamma size for reporting to userspace */
|
||||
uint32_t gamma_size;
|
||||
uint16_t *gamma_store;
|
||||
|
||||
|
@ -1677,6 +1690,7 @@ struct drm_bridge {
|
|||
* @dev: parent DRM device
|
||||
* @allow_modeset: allow full modeset
|
||||
* @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics
|
||||
* @legacy_set_config: Disable conflicting encoders instead of failing with -EINVAL.
|
||||
* @planes: pointer to array of plane pointers
|
||||
* @plane_states: pointer to array of plane states pointers
|
||||
* @crtcs: pointer to array of CRTC pointers
|
||||
|
@ -1690,6 +1704,7 @@ struct drm_atomic_state {
|
|||
struct drm_device *dev;
|
||||
bool allow_modeset : 1;
|
||||
bool legacy_cursor_update : 1;
|
||||
bool legacy_set_config : 1;
|
||||
struct drm_plane **planes;
|
||||
struct drm_plane_state **plane_states;
|
||||
struct drm_crtc **crtcs;
|
||||
|
@ -2026,6 +2041,15 @@ struct drm_mode_config_funcs {
|
|||
* @property_blob_list: list of all the blob property objects
|
||||
* @blob_lock: mutex for blob property allocation and management
|
||||
* @*_property: core property tracking
|
||||
* @degamma_lut_property: LUT used to convert the framebuffer's colors to linear
|
||||
* gamma
|
||||
* @degamma_lut_size_property: size of the degamma LUT as supported by the
|
||||
* driver (read-only)
|
||||
* @ctm_property: Matrix used to convert colors after the lookup in the
|
||||
* degamma LUT
|
||||
* @gamma_lut_property: LUT used to convert the colors, after the CSC matrix, to
|
||||
* the gamma space of the connected screen (read-only)
|
||||
* @gamma_lut_size_property: size of the gamma LUT as supported by the driver
|
||||
* @preferred_depth: preferred RBG pixel depth, used by fb helpers
|
||||
* @prefer_shadow: hint to userspace to prefer shadow-fb rendering
|
||||
* @async_page_flip: does this device support async flips on the primary plane?
|
||||
|
@ -2128,6 +2152,13 @@ struct drm_mode_config {
|
|||
struct drm_property *aspect_ratio_property;
|
||||
struct drm_property *dirty_info_property;
|
||||
|
||||
/* Optional color correction properties */
|
||||
struct drm_property *degamma_lut_property;
|
||||
struct drm_property *degamma_lut_size_property;
|
||||
struct drm_property *ctm_property;
|
||||
struct drm_property *gamma_lut_property;
|
||||
struct drm_property *gamma_lut_size_property;
|
||||
|
||||
/* properties for virtual machine layout */
|
||||
struct drm_property *suggested_x_property;
|
||||
struct drm_property *suggested_y_property;
|
||||
|
@ -2554,6 +2585,21 @@ static inline struct drm_property *drm_property_find(struct drm_device *dev,
|
|||
return mo ? obj_to_property(mo) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extract a degamma/gamma LUT value provided by user and round it to the
|
||||
* precision supported by the hardware.
|
||||
*/
|
||||
static inline uint32_t drm_color_lut_extract(uint32_t user_input,
|
||||
uint32_t bit_precision)
|
||||
{
|
||||
uint32_t val = user_input + (1 << (16 - bit_precision - 1));
|
||||
uint32_t max = 0xffff >> (16 - bit_precision);
|
||||
|
||||
val >>= 16 - bit_precision;
|
||||
|
||||
return clamp_val(val, 0, max);
|
||||
}
|
||||
|
||||
/* Plane list iterator for legacy (overlay only) planes. */
|
||||
#define drm_for_each_legacy_plane(plane, dev) \
|
||||
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \
|
||||
|
|
|
@ -48,6 +48,9 @@ extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
|
|||
struct drm_display_mode *mode,
|
||||
int x, int y,
|
||||
struct drm_framebuffer *old_fb);
|
||||
extern void drm_helper_crtc_enable_color_mgmt(struct drm_crtc *crtc,
|
||||
int degamma_lut_size,
|
||||
int gamma_lut_size);
|
||||
extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
|
||||
extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder);
|
||||
|
||||
|
|
|
@ -487,6 +487,21 @@ struct drm_mode_crtc_lut {
|
|||
__u64 blue;
|
||||
};
|
||||
|
||||
struct drm_color_ctm {
|
||||
/* Conversion matrix in S31.32 format. */
|
||||
__s64 matrix[9];
|
||||
};
|
||||
|
||||
struct drm_color_lut {
|
||||
/*
|
||||
* Data is U0.16 fixed point format.
|
||||
*/
|
||||
__u16 red;
|
||||
__u16 green;
|
||||
__u16 blue;
|
||||
__u16 reserved;
|
||||
};
|
||||
|
||||
#define DRM_MODE_PAGE_FLIP_EVENT 0x01
|
||||
#define DRM_MODE_PAGE_FLIP_ASYNC 0x02
|
||||
#define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT|DRM_MODE_PAGE_FLIP_ASYNC)
|
||||
|
|
Loading…
Reference in a new issue