Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.
...

+544 -300
+57 -2
Documentation/DocBook/gpu.tmpl
··· 1816 1816 <td valign="top" >Description/Restrictions</td> 1817 1817 </tr> 1818 1818 <tr> 1819 - <td rowspan="37" valign="top" >DRM</td> 1819 + <td rowspan="42" valign="top" >DRM</td> 1820 1820 <td valign="top" >Generic</td> 1821 1821 <td valign="top" >“rotation”</td> 1822 1822 <td valign="top" >BITMASK</td> ··· 2068 2068 <td valign="top" >property to suggest an Y offset for a connector</td> 2069 2069 </tr> 2070 2070 <tr> 2071 - <td rowspan="3" valign="top" >Optional</td> 2071 + <td rowspan="8" valign="top" >Optional</td> 2072 2072 <td valign="top" >“scaling mode”</td> 2073 2073 <td valign="top" >ENUM</td> 2074 2074 <td valign="top" >{ "None", "Full", "Center", "Full aspect" }</td> ··· 2090 2090 <td valign="top" >{ "Off", "On", "Annotate" }</td> 2091 2091 <td valign="top" >Connector</td> 2092 2092 <td valign="top" >TBD</td> 2093 + </tr> 2094 + <tr> 2095 + <td valign="top" >“DEGAMMA_LUT”</td> 2096 + <td valign="top" >BLOB</td> 2097 + <td valign="top" >0</td> 2098 + <td valign="top" >CRTC</td> 2099 + <td valign="top" >DRM property to set the degamma lookup table 2100 + (LUT) mapping pixel data from the framebuffer before it is 2101 + given to the transformation matrix. The data is an interpreted 2102 + as an array of struct drm_color_lut elements. Hardware might 2103 + choose not to use the full precision of the LUT elements nor 2104 + use all the elements of the LUT (for example the hardware 2105 + might choose to interpolate between LUT[0] and LUT[4]). </td> 2106 + </tr> 2107 + <tr> 2108 + <td valign="top" >“DEGAMMA_LUT_SIZE”</td> 2109 + <td valign="top" >RANGE | IMMUTABLE</td> 2110 + <td valign="top" >Min=0, Max=UINT_MAX</td> 2111 + <td valign="top" >CRTC</td> 2112 + <td valign="top" >DRM property to gives the size of the lookup 2113 + table to be set on the DEGAMMA_LUT property (the size depends 2114 + on the underlying hardware).</td> 2115 + </tr> 2116 + <tr> 2117 + <td valign="top" >“CTM”</td> 2118 + <td valign="top" >BLOB</td> 2119 + <td valign="top" >0</td> 2120 + <td valign="top" >CRTC</td> 2121 + <td valign="top" >DRM property to set the current 2122 + transformation matrix (CTM) apply to pixel data after the 2123 + lookup through the degamma LUT and before the lookup through 2124 + the gamma LUT. The data is an interpreted as a struct 2125 + drm_color_ctm.</td> 2126 + </tr> 2127 + <tr> 2128 + <td valign="top" >“GAMMA_LUT”</td> 2129 + <td valign="top" >BLOB</td> 2130 + <td valign="top" >0</td> 2131 + <td valign="top" >CRTC</td> 2132 + <td valign="top" >DRM property to set the gamma lookup table 2133 + (LUT) mapping pixel data after to the transformation matrix to 2134 + data sent to the connector. The data is an interpreted as an 2135 + array of struct drm_color_lut elements. Hardware might choose 2136 + not to use the full precision of the LUT elements nor use all 2137 + the elements of the LUT (for example the hardware might choose 2138 + to interpolate between LUT[0] and LUT[4]).</td> 2139 + </tr> 2140 + <tr> 2141 + <td valign="top" >“GAMMA_LUT_SIZE”</td> 2142 + <td valign="top" >RANGE | IMMUTABLE</td> 2143 + <td valign="top" >Min=0, Max=UINT_MAX</td> 2144 + <td valign="top" >CRTC</td> 2145 + <td valign="top" >DRM property to gives the size of the lookup 2146 + table to be set on the GAMMA_LUT property (the size depends on 2147 + the underlying hardware).</td> 2093 2148 </tr> 2094 2149 <tr> 2095 2150 <td rowspan="20" valign="top" >i915</td>
-8
drivers/gpu/drm/ast/ast_mode.c
··· 497 497 } 498 498 } 499 499 500 - static bool ast_crtc_mode_fixup(struct drm_crtc *crtc, 501 - const struct drm_display_mode *mode, 502 - struct drm_display_mode *adjusted_mode) 503 - { 504 - return true; 505 - } 506 - 507 500 /* ast is different - we will force move buffers out of VRAM */ 508 501 static int ast_crtc_do_set_base(struct drm_crtc *crtc, 509 502 struct drm_framebuffer *fb, ··· 610 617 611 618 static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { 612 619 .dpms = ast_crtc_dpms, 613 - .mode_fixup = ast_crtc_mode_fixup, 614 620 .mode_set = ast_crtc_mode_set, 615 621 .mode_set_base = ast_crtc_mode_set_base, 616 622 .disable = ast_crtc_disable,
-9
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
··· 121 121 cfg); 122 122 } 123 123 124 - static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *crtc, 125 - const struct drm_display_mode *mode, 126 - struct drm_display_mode *adjusted_mode) 127 - { 128 - return true; 129 - } 130 - 131 124 static void atmel_hlcdc_crtc_disable(struct drm_crtc *c) 132 125 { 133 126 struct drm_device *dev = c->dev; ··· 254 261 } 255 262 256 263 static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { 257 - .mode_fixup = atmel_hlcdc_crtc_mode_fixup, 258 264 .mode_set = drm_helper_crtc_mode_set, 259 265 .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb, 260 266 .mode_set_base = drm_helper_crtc_mode_set_base, ··· 341 349 atmel_hlcdc_crtc_destroy(&crtc->base); 342 350 return ret; 343 351 } 344 -
-8
drivers/gpu/drm/bochs/bochs_kms.c
··· 30 30 } 31 31 } 32 32 33 - static bool bochs_crtc_mode_fixup(struct drm_crtc *crtc, 34 - const struct drm_display_mode *mode, 35 - struct drm_display_mode *adjusted_mode) 36 - { 37 - return true; 38 - } 39 - 40 33 static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, 41 34 struct drm_framebuffer *old_fb) 42 35 { ··· 128 135 129 136 static const struct drm_crtc_helper_funcs bochs_helper_funcs = { 130 137 .dpms = bochs_crtc_dpms, 131 - .mode_fixup = bochs_crtc_mode_fixup, 132 138 .mode_set = bochs_crtc_mode_set, 133 139 .mode_set_base = bochs_crtc_mode_set_base, 134 140 .prepare = bochs_crtc_prepare,
-13
drivers/gpu/drm/cirrus/cirrus_mode.c
··· 91 91 WREG_GFX(0xe, gr0e); 92 92 } 93 93 94 - /* 95 - * The core passes the desired mode to the CRTC code to see whether any 96 - * CRTC-specific modifications need to be made to it. We're in a position 97 - * to just pass that straight through, so this does nothing 98 - */ 99 - static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc, 100 - const struct drm_display_mode *mode, 101 - struct drm_display_mode *adjusted_mode) 102 - { 103 - return true; 104 - } 105 - 106 94 static void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset) 107 95 { 108 96 struct cirrus_device *cdev = crtc->dev->dev_private; ··· 360 372 361 373 static const struct drm_crtc_helper_funcs cirrus_helper_funcs = { 362 374 .dpms = cirrus_crtc_dpms, 363 - .mode_fixup = cirrus_crtc_mode_fixup, 364 375 .mode_set = cirrus_crtc_mode_set, 365 376 .mode_set_base = cirrus_crtc_mode_set_base, 366 377 .prepare = cirrus_crtc_prepare,
+86 -2
drivers/gpu/drm/drm_atomic.c
··· 28 28 29 29 #include <drm/drmP.h> 30 30 #include <drm/drm_atomic.h> 31 + #include <drm/drm_mode.h> 31 32 #include <drm/drm_plane_helper.h> 32 33 33 34 /** ··· 377 376 EXPORT_SYMBOL(drm_atomic_set_mode_prop_for_crtc); 378 377 379 378 /** 379 + * drm_atomic_replace_property_blob - replace a blob property 380 + * @blob: a pointer to the member blob to be replaced 381 + * @new_blob: the new blob to replace with 382 + * @expected_size: the expected size of the new blob 383 + * @replaced: whether the blob has been replaced 384 + * 385 + * RETURNS: 386 + * Zero on success, error code on failure 387 + */ 388 + static void 389 + drm_atomic_replace_property_blob(struct drm_property_blob **blob, 390 + struct drm_property_blob *new_blob, 391 + bool *replaced) 392 + { 393 + struct drm_property_blob *old_blob = *blob; 394 + 395 + if (old_blob == new_blob) 396 + return; 397 + 398 + if (old_blob) 399 + drm_property_unreference_blob(old_blob); 400 + if (new_blob) 401 + drm_property_reference_blob(new_blob); 402 + *blob = new_blob; 403 + *replaced = true; 404 + 405 + return; 406 + } 407 + 408 + static int 409 + drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc, 410 + struct drm_property_blob **blob, 411 + uint64_t blob_id, 412 + ssize_t expected_size, 413 + bool *replaced) 414 + { 415 + struct drm_device *dev = crtc->dev; 416 + struct drm_property_blob *new_blob = NULL; 417 + 418 + if (blob_id != 0) { 419 + new_blob = drm_property_lookup_blob(dev, blob_id); 420 + if (new_blob == NULL) 421 + return -EINVAL; 422 + if (expected_size > 0 && expected_size != new_blob->length) 423 + return -EINVAL; 424 + } 425 + 426 + drm_atomic_replace_property_blob(blob, new_blob, replaced); 427 + 428 + return 0; 429 + } 430 + 431 + /** 380 432 * drm_atomic_crtc_set_property - set property on CRTC 381 433 * @crtc: the drm CRTC to set a property on 382 434 * @state: the state object to update with the new property value ··· 451 397 { 452 398 struct drm_device *dev = crtc->dev; 453 399 struct drm_mode_config *config = &dev->mode_config; 400 + bool replaced = false; 454 401 int ret; 455 402 456 403 if (property == config->prop_active) ··· 462 407 ret = drm_atomic_set_mode_prop_for_crtc(state, mode); 463 408 drm_property_unreference_blob(mode); 464 409 return ret; 465 - } 466 - else if (crtc->funcs->atomic_set_property) 410 + } else if (property == config->degamma_lut_property) { 411 + ret = drm_atomic_replace_property_blob_from_id(crtc, 412 + &state->degamma_lut, 413 + val, 414 + -1, 415 + &replaced); 416 + state->color_mgmt_changed = replaced; 417 + return ret; 418 + } else if (property == config->ctm_property) { 419 + ret = drm_atomic_replace_property_blob_from_id(crtc, 420 + &state->ctm, 421 + val, 422 + sizeof(struct drm_color_ctm), 423 + &replaced); 424 + state->color_mgmt_changed = replaced; 425 + return ret; 426 + } else if (property == config->gamma_lut_property) { 427 + ret = drm_atomic_replace_property_blob_from_id(crtc, 428 + &state->gamma_lut, 429 + val, 430 + -1, 431 + &replaced); 432 + state->color_mgmt_changed = replaced; 433 + return ret; 434 + } else if (crtc->funcs->atomic_set_property) 467 435 return crtc->funcs->atomic_set_property(crtc, state, property, val); 468 436 else 469 437 return -EINVAL; ··· 522 444 *val = state->active; 523 445 else if (property == config->prop_mode_id) 524 446 *val = (state->mode_blob) ? state->mode_blob->base.id : 0; 447 + else if (property == config->degamma_lut_property) 448 + *val = (state->degamma_lut) ? state->degamma_lut->base.id : 0; 449 + else if (property == config->ctm_property) 450 + *val = (state->ctm) ? state->ctm->base.id : 0; 451 + else if (property == config->gamma_lut_property) 452 + *val = (state->gamma_lut) ? state->gamma_lut->base.id : 0; 525 453 else if (crtc->funcs->atomic_get_property) 526 454 return crtc->funcs->atomic_get_property(crtc, state, property, val); 527 455 else
+247 -131
drivers/gpu/drm/drm_atomic_helper.c
··· 86 86 } 87 87 } 88 88 89 - static bool 90 - check_pending_encoder_assignment(struct drm_atomic_state *state, 91 - struct drm_encoder *new_encoder) 89 + static int handle_conflicting_encoders(struct drm_atomic_state *state, 90 + bool disable_conflicting_encoders) 92 91 { 93 - struct drm_connector *connector; 94 92 struct drm_connector_state *conn_state; 95 - int i; 96 - 97 - for_each_connector_in_state(state, connector, conn_state, i) { 98 - if (conn_state->best_encoder != new_encoder) 99 - continue; 100 - 101 - /* encoder already assigned and we're trying to re-steal it! */ 102 - if (connector->state->best_encoder != conn_state->best_encoder) 103 - return false; 104 - } 105 - 106 - return true; 107 - } 108 - 109 - static struct drm_crtc * 110 - get_current_crtc_for_encoder(struct drm_device *dev, 111 - struct drm_encoder *encoder) 112 - { 113 - struct drm_mode_config *config = &dev->mode_config; 114 93 struct drm_connector *connector; 94 + struct drm_encoder *encoder; 95 + unsigned encoder_mask = 0; 96 + int i, ret; 115 97 116 - WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); 98 + /* 99 + * First loop, find all newly assigned encoders from the connectors 100 + * part of the state. If the same encoder is assigned to multiple 101 + * connectors bail out. 102 + */ 103 + for_each_connector_in_state(state, connector, conn_state, i) { 104 + const struct drm_connector_helper_funcs *funcs = connector->helper_private; 105 + struct drm_encoder *new_encoder; 117 106 118 - drm_for_each_connector(connector, dev) { 119 - if (connector->state->best_encoder != encoder) 107 + if (!conn_state->crtc) 120 108 continue; 121 109 122 - return connector->state->crtc; 110 + if (funcs->atomic_best_encoder) 111 + new_encoder = funcs->atomic_best_encoder(connector, conn_state); 112 + else 113 + new_encoder = funcs->best_encoder(connector); 114 + 115 + if (new_encoder) { 116 + if (encoder_mask & (1 << drm_encoder_index(new_encoder))) { 117 + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] on [CONNECTOR:%d:%s] already assigned\n", 118 + new_encoder->base.id, new_encoder->name, 119 + connector->base.id, connector->name); 120 + 121 + return -EINVAL; 122 + } 123 + 124 + encoder_mask |= 1 << drm_encoder_index(new_encoder); 125 + } 123 126 } 124 127 125 - return NULL; 128 + if (!encoder_mask) 129 + return 0; 130 + 131 + /* 132 + * Second loop, iterate over all connectors not part of the state. 133 + * 134 + * If a conflicting encoder is found and disable_conflicting_encoders 135 + * is not set, an error is returned. Userspace can provide a solution 136 + * through the atomic ioctl. 137 + * 138 + * If the flag is set conflicting connectors are removed from the crtc 139 + * and the crtc is disabled if no encoder is left. This preserves 140 + * compatibility with the legacy set_config behavior. 141 + */ 142 + drm_for_each_connector(connector, state->dev) { 143 + struct drm_crtc_state *crtc_state; 144 + 145 + if (drm_atomic_get_existing_connector_state(state, connector)) 146 + continue; 147 + 148 + encoder = connector->state->best_encoder; 149 + if (!encoder || !(encoder_mask & (1 << drm_encoder_index(encoder)))) 150 + continue; 151 + 152 + if (!disable_conflicting_encoders) { 153 + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s] by [CONNECTOR:%d:%s]\n", 154 + encoder->base.id, encoder->name, 155 + connector->state->crtc->base.id, 156 + connector->state->crtc->name, 157 + connector->base.id, connector->name); 158 + return -EINVAL; 159 + } 160 + 161 + conn_state = drm_atomic_get_connector_state(state, connector); 162 + if (IS_ERR(conn_state)) 163 + return PTR_ERR(conn_state); 164 + 165 + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n", 166 + encoder->base.id, encoder->name, 167 + conn_state->crtc->base.id, conn_state->crtc->name, 168 + connector->base.id, connector->name); 169 + 170 + crtc_state = drm_atomic_get_existing_crtc_state(state, conn_state->crtc); 171 + 172 + ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); 173 + if (ret) 174 + return ret; 175 + 176 + if (!crtc_state->connector_mask) { 177 + ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, 178 + NULL); 179 + if (ret < 0) 180 + return ret; 181 + 182 + crtc_state->active = false; 183 + } 184 + } 185 + 186 + return 0; 126 187 } 127 188 128 189 static void ··· 227 166 conn_state->best_encoder = encoder; 228 167 } 229 168 230 - static int 169 + static void 231 170 steal_encoder(struct drm_atomic_state *state, 232 - struct drm_encoder *encoder, 233 - struct drm_crtc *encoder_crtc) 171 + struct drm_encoder *encoder) 234 172 { 235 - struct drm_mode_config *config = &state->dev->mode_config; 236 173 struct drm_crtc_state *crtc_state; 237 174 struct drm_connector *connector; 238 175 struct drm_connector_state *connector_state; 176 + int i; 239 177 240 - /* 241 - * We can only steal an encoder coming from a connector, which means we 242 - * must already hold the connection_mutex. 243 - */ 244 - WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); 245 - 246 - DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", 247 - encoder->base.id, encoder->name, 248 - encoder_crtc->base.id, encoder_crtc->name); 249 - 250 - crtc_state = drm_atomic_get_crtc_state(state, encoder_crtc); 251 - if (IS_ERR(crtc_state)) 252 - return PTR_ERR(crtc_state); 253 - 254 - crtc_state->connectors_changed = true; 255 - 256 - list_for_each_entry(connector, &config->connector_list, head) { 257 - if (connector->state->best_encoder != encoder) 258 - continue; 259 - 260 - DRM_DEBUG_ATOMIC("Stealing encoder from [CONNECTOR:%d:%s]\n", 261 - connector->base.id, 262 - connector->name); 263 - 264 - connector_state = drm_atomic_get_connector_state(state, 265 - connector); 266 - if (IS_ERR(connector_state)) 267 - return PTR_ERR(connector_state); 178 + for_each_connector_in_state(state, connector, connector_state, i) { 179 + struct drm_crtc *encoder_crtc; 268 180 269 181 if (connector_state->best_encoder != encoder) 270 182 continue; 271 183 272 - set_best_encoder(state, connector_state, NULL); 273 - } 184 + encoder_crtc = connector->state->crtc; 274 185 275 - return 0; 186 + DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], stealing it\n", 187 + encoder->base.id, encoder->name, 188 + encoder_crtc->base.id, encoder_crtc->name); 189 + 190 + set_best_encoder(state, connector_state, NULL); 191 + 192 + crtc_state = drm_atomic_get_existing_crtc_state(state, encoder_crtc); 193 + crtc_state->connectors_changed = true; 194 + 195 + return; 196 + } 276 197 } 277 198 278 199 static int 279 - update_connector_routing(struct drm_atomic_state *state, int conn_idx) 200 + update_connector_routing(struct drm_atomic_state *state, 201 + struct drm_connector *connector, 202 + struct drm_connector_state *connector_state) 280 203 { 281 204 const struct drm_connector_helper_funcs *funcs; 282 205 struct drm_encoder *new_encoder; 283 - struct drm_crtc *encoder_crtc; 284 - struct drm_connector *connector; 285 - struct drm_connector_state *connector_state; 286 206 struct drm_crtc_state *crtc_state; 287 - int idx, ret; 288 - 289 - connector = state->connectors[conn_idx]; 290 - connector_state = state->connector_states[conn_idx]; 291 - 292 - if (!connector) 293 - return 0; 294 207 295 208 DRM_DEBUG_ATOMIC("Updating routing for [CONNECTOR:%d:%s]\n", 296 209 connector->base.id, ··· 272 237 273 238 if (connector->state->crtc != connector_state->crtc) { 274 239 if (connector->state->crtc) { 275 - idx = drm_crtc_index(connector->state->crtc); 276 - 277 - crtc_state = state->crtc_states[idx]; 240 + crtc_state = drm_atomic_get_existing_crtc_state(state, connector->state->crtc); 278 241 crtc_state->connectors_changed = true; 279 242 } 280 243 281 244 if (connector_state->crtc) { 282 - idx = drm_crtc_index(connector_state->crtc); 283 - 284 - crtc_state = state->crtc_states[idx]; 245 + crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc); 285 246 crtc_state->connectors_changed = true; 286 247 } 287 248 } ··· 329 298 return 0; 330 299 } 331 300 332 - if (!check_pending_encoder_assignment(state, new_encoder)) { 333 - DRM_DEBUG_ATOMIC("Encoder for [CONNECTOR:%d:%s] already assigned\n", 334 - connector->base.id, 335 - connector->name); 336 - return -EINVAL; 337 - } 338 - 339 - encoder_crtc = get_current_crtc_for_encoder(state->dev, 340 - new_encoder); 341 - 342 - if (encoder_crtc) { 343 - ret = steal_encoder(state, new_encoder, encoder_crtc); 344 - if (ret) { 345 - DRM_DEBUG_ATOMIC("Encoder stealing failed for [CONNECTOR:%d:%s]\n", 346 - connector->base.id, 347 - connector->name); 348 - return ret; 349 - } 350 - } 351 - 352 - if (WARN_ON(!connector_state->crtc)) 353 - return -EINVAL; 301 + steal_encoder(state, new_encoder); 354 302 355 303 set_best_encoder(state, connector_state, new_encoder); 356 304 357 - idx = drm_crtc_index(connector_state->crtc); 358 - 359 - crtc_state = state->crtc_states[idx]; 305 + crtc_state = drm_atomic_get_existing_crtc_state(state, connector_state->crtc); 360 306 crtc_state->connectors_changed = true; 361 307 362 308 DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", ··· 496 488 } 497 489 } 498 490 491 + ret = handle_conflicting_encoders(state, state->legacy_set_config); 492 + if (ret) 493 + return ret; 494 + 499 495 for_each_connector_in_state(state, connector, connector_state, i) { 500 496 /* 501 497 * This only sets crtc->mode_changed for routing changes, 502 498 * drivers must set crtc->mode_changed themselves when connector 503 499 * properties need to be updated. 504 500 */ 505 - ret = update_connector_routing(state, i); 501 + ret = update_connector_routing(state, connector, 502 + connector_state); 506 503 if (ret) 507 504 return ret; 508 505 } ··· 1774 1761 struct drm_crtc_state *crtc_state; 1775 1762 struct drm_connector *connector; 1776 1763 struct drm_connector_state *conn_state; 1777 - int ret, i, j; 1764 + int ret, i; 1778 1765 1779 1766 ret = drm_modeset_lock(&dev->mode_config.connection_mutex, 1780 1767 state->acquire_ctx); 1781 1768 if (ret) 1782 1769 return ret; 1783 1770 1784 - /* First grab all affected connector/crtc states. */ 1785 - for (i = 0; i < set->num_connectors; i++) { 1786 - conn_state = drm_atomic_get_connector_state(state, 1787 - set->connectors[i]); 1788 - if (IS_ERR(conn_state)) 1789 - return PTR_ERR(conn_state); 1790 - } 1771 + /* First disable all connectors on the target crtc. */ 1772 + ret = drm_atomic_add_affected_connectors(state, set->crtc); 1773 + if (ret) 1774 + return ret; 1791 1775 1792 - for_each_crtc_in_state(state, crtc, crtc_state, i) { 1793 - ret = drm_atomic_add_affected_connectors(state, crtc); 1794 - if (ret) 1795 - return ret; 1796 - } 1797 - 1798 - /* Then recompute connector->crtc links and crtc enabling state. */ 1799 1776 for_each_connector_in_state(state, connector, conn_state, i) { 1800 1777 if (conn_state->crtc == set->crtc) { 1801 1778 ret = drm_atomic_set_crtc_for_connector(conn_state, ··· 1793 1790 if (ret) 1794 1791 return ret; 1795 1792 } 1793 + } 1796 1794 1797 - for (j = 0; j < set->num_connectors; j++) { 1798 - if (set->connectors[j] == connector) { 1799 - ret = drm_atomic_set_crtc_for_connector(conn_state, 1800 - set->crtc); 1801 - if (ret) 1802 - return ret; 1803 - break; 1804 - } 1805 - } 1795 + /* Then set all connectors from set->connectors on the target crtc */ 1796 + for (i = 0; i < set->num_connectors; i++) { 1797 + conn_state = drm_atomic_get_connector_state(state, 1798 + set->connectors[i]); 1799 + if (IS_ERR(conn_state)) 1800 + return PTR_ERR(conn_state); 1801 + 1802 + ret = drm_atomic_set_crtc_for_connector(conn_state, 1803 + set->crtc); 1804 + if (ret) 1805 + return ret; 1806 1806 } 1807 1807 1808 1808 for_each_crtc_in_state(state, crtc, crtc_state, i) { ··· 1848 1842 if (!state) 1849 1843 return -ENOMEM; 1850 1844 1845 + state->legacy_set_config = true; 1851 1846 state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); 1852 1847 retry: 1853 1848 ret = __drm_atomic_helper_set_config(set, state); ··· 2495 2488 */ 2496 2489 void drm_atomic_helper_crtc_reset(struct drm_crtc *crtc) 2497 2490 { 2498 - if (crtc->state) 2491 + if (crtc->state) { 2499 2492 drm_property_unreference_blob(crtc->state->mode_blob); 2493 + drm_property_unreference_blob(crtc->state->degamma_lut); 2494 + drm_property_unreference_blob(crtc->state->ctm); 2495 + drm_property_unreference_blob(crtc->state->gamma_lut); 2496 + } 2500 2497 kfree(crtc->state); 2501 2498 crtc->state = kzalloc(sizeof(*crtc->state), GFP_KERNEL); 2502 2499 ··· 2524 2513 2525 2514 if (state->mode_blob) 2526 2515 drm_property_reference_blob(state->mode_blob); 2516 + if (state->degamma_lut) 2517 + drm_property_reference_blob(state->degamma_lut); 2518 + if (state->ctm) 2519 + drm_property_reference_blob(state->ctm); 2520 + if (state->gamma_lut) 2521 + drm_property_reference_blob(state->gamma_lut); 2527 2522 state->mode_changed = false; 2528 2523 state->active_changed = false; 2529 2524 state->planes_changed = false; 2530 2525 state->connectors_changed = false; 2526 + state->color_mgmt_changed = false; 2531 2527 state->event = NULL; 2532 2528 } 2533 2529 EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); ··· 2575 2557 struct drm_crtc_state *state) 2576 2558 { 2577 2559 drm_property_unreference_blob(state->mode_blob); 2560 + drm_property_unreference_blob(state->degamma_lut); 2561 + drm_property_unreference_blob(state->ctm); 2562 + drm_property_unreference_blob(state->gamma_lut); 2578 2563 } 2579 2564 EXPORT_SYMBOL(__drm_atomic_helper_crtc_destroy_state); 2580 2565 ··· 2891 2870 kfree(state); 2892 2871 } 2893 2872 EXPORT_SYMBOL(drm_atomic_helper_connector_destroy_state); 2873 + 2874 + /** 2875 + * drm_atomic_helper_legacy_gamma_set - set the legacy gamma correction table 2876 + * @crtc: CRTC object 2877 + * @red: red correction table 2878 + * @green: green correction table 2879 + * @blue: green correction table 2880 + * @start: 2881 + * @size: size of the tables 2882 + * 2883 + * Implements support for legacy gamma correction table for drivers 2884 + * that support color management through the DEGAMMA_LUT/GAMMA_LUT 2885 + * properties. 2886 + */ 2887 + void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, 2888 + u16 *red, u16 *green, u16 *blue, 2889 + uint32_t start, uint32_t size) 2890 + { 2891 + struct drm_device *dev = crtc->dev; 2892 + struct drm_mode_config *config = &dev->mode_config; 2893 + struct drm_atomic_state *state; 2894 + struct drm_crtc_state *crtc_state; 2895 + struct drm_property_blob *blob = NULL; 2896 + struct drm_color_lut *blob_data; 2897 + int i, ret = 0; 2898 + 2899 + state = drm_atomic_state_alloc(crtc->dev); 2900 + if (!state) 2901 + return; 2902 + 2903 + blob = drm_property_create_blob(dev, 2904 + sizeof(struct drm_color_lut) * size, 2905 + NULL); 2906 + if (IS_ERR(blob)) { 2907 + ret = PTR_ERR(blob); 2908 + blob = NULL; 2909 + goto fail; 2910 + } 2911 + 2912 + /* Prepare GAMMA_LUT with the legacy values. */ 2913 + blob_data = (struct drm_color_lut *) blob->data; 2914 + for (i = 0; i < size; i++) { 2915 + blob_data[i].red = red[i]; 2916 + blob_data[i].green = green[i]; 2917 + blob_data[i].blue = blue[i]; 2918 + } 2919 + 2920 + state->acquire_ctx = crtc->dev->mode_config.acquire_ctx; 2921 + retry: 2922 + crtc_state = drm_atomic_get_crtc_state(state, crtc); 2923 + if (IS_ERR(crtc_state)) { 2924 + ret = PTR_ERR(crtc_state); 2925 + goto fail; 2926 + } 2927 + 2928 + /* Reset DEGAMMA_LUT and CTM properties. */ 2929 + ret = drm_atomic_crtc_set_property(crtc, crtc_state, 2930 + config->degamma_lut_property, 0); 2931 + if (ret) 2932 + goto fail; 2933 + 2934 + ret = drm_atomic_crtc_set_property(crtc, crtc_state, 2935 + config->ctm_property, 0); 2936 + if (ret) 2937 + goto fail; 2938 + 2939 + ret = drm_atomic_crtc_set_property(crtc, crtc_state, 2940 + config->gamma_lut_property, blob->base.id); 2941 + if (ret) 2942 + goto fail; 2943 + 2944 + ret = drm_atomic_commit(state); 2945 + if (ret) 2946 + goto fail; 2947 + 2948 + /* Driver takes ownership of state on successful commit. */ 2949 + 2950 + drm_property_unreference_blob(blob); 2951 + 2952 + return; 2953 + fail: 2954 + if (ret == -EDEADLK) 2955 + goto backoff; 2956 + 2957 + drm_atomic_state_free(state); 2958 + drm_property_unreference_blob(blob); 2959 + 2960 + return; 2961 + backoff: 2962 + drm_atomic_state_clear(state); 2963 + drm_atomic_legacy_backoff(state); 2964 + 2965 + goto retry; 2966 + } 2967 + EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set);
+36 -3
drivers/gpu/drm/drm_crtc.c
··· 430 430 static void __drm_framebuffer_unregister(struct drm_device *dev, 431 431 struct drm_framebuffer *fb) 432 432 { 433 - mutex_lock(&dev->mode_config.idr_mutex); 434 - idr_remove(&dev->mode_config.crtc_idr, fb->base.id); 435 - mutex_unlock(&dev->mode_config.idr_mutex); 433 + drm_mode_object_put(dev, &fb->base); 436 434 437 435 fb->base.id = 0; 438 436 } ··· 1551 1553 if (!prop) 1552 1554 return -ENOMEM; 1553 1555 dev->mode_config.prop_mode_id = prop; 1556 + 1557 + prop = drm_property_create(dev, 1558 + DRM_MODE_PROP_BLOB, 1559 + "DEGAMMA_LUT", 0); 1560 + if (!prop) 1561 + return -ENOMEM; 1562 + dev->mode_config.degamma_lut_property = prop; 1563 + 1564 + prop = drm_property_create_range(dev, 1565 + DRM_MODE_PROP_IMMUTABLE, 1566 + "DEGAMMA_LUT_SIZE", 0, UINT_MAX); 1567 + if (!prop) 1568 + return -ENOMEM; 1569 + dev->mode_config.degamma_lut_size_property = prop; 1570 + 1571 + prop = drm_property_create(dev, 1572 + DRM_MODE_PROP_BLOB, 1573 + "CTM", 0); 1574 + if (!prop) 1575 + return -ENOMEM; 1576 + dev->mode_config.ctm_property = prop; 1577 + 1578 + prop = drm_property_create(dev, 1579 + DRM_MODE_PROP_BLOB, 1580 + "GAMMA_LUT", 0); 1581 + if (!prop) 1582 + return -ENOMEM; 1583 + dev->mode_config.gamma_lut_property = prop; 1584 + 1585 + prop = drm_property_create_range(dev, 1586 + DRM_MODE_PROP_IMMUTABLE, 1587 + "GAMMA_LUT_SIZE", 0, UINT_MAX); 1588 + if (!prop) 1589 + return -ENOMEM; 1590 + dev->mode_config.gamma_lut_size_property = prop; 1554 1591 1555 1592 return 0; 1556 1593 }
+33
drivers/gpu/drm/drm_crtc_helper.c
··· 1075 1075 return drm_plane_helper_commit(plane, plane_state, old_fb); 1076 1076 } 1077 1077 EXPORT_SYMBOL(drm_helper_crtc_mode_set_base); 1078 + 1079 + /** 1080 + * drm_helper_crtc_enable_color_mgmt - enable color management properties 1081 + * @crtc: DRM CRTC 1082 + * @degamma_lut_size: the size of the degamma lut (before CSC) 1083 + * @gamma_lut_size: the size of the gamma lut (after CSC) 1084 + * 1085 + * This function lets the driver enable the color correction properties on a 1086 + * CRTC. This includes 3 degamma, csc and gamma properties that userspace can 1087 + * set and 2 size properties to inform the userspace of the lut sizes. 1088 + */ 1089 + void drm_helper_crtc_enable_color_mgmt(struct drm_crtc *crtc, 1090 + int degamma_lut_size, 1091 + int gamma_lut_size) 1092 + { 1093 + struct drm_device *dev = crtc->dev; 1094 + struct drm_mode_config *config = &dev->mode_config; 1095 + 1096 + drm_object_attach_property(&crtc->base, 1097 + config->degamma_lut_property, 0); 1098 + drm_object_attach_property(&crtc->base, 1099 + config->ctm_property, 0); 1100 + drm_object_attach_property(&crtc->base, 1101 + config->gamma_lut_property, 0); 1102 + 1103 + drm_object_attach_property(&crtc->base, 1104 + config->degamma_lut_size_property, 1105 + degamma_lut_size); 1106 + drm_object_attach_property(&crtc->base, 1107 + config->gamma_lut_size_property, 1108 + gamma_lut_size); 1109 + } 1110 + EXPORT_SYMBOL(drm_helper_crtc_enable_color_mgmt);
+11 -6
drivers/gpu/drm/drm_edid.c
··· 3308 3308 u8 *cea; 3309 3309 u8 *name; 3310 3310 u8 *db; 3311 - int sad_count = 0; 3311 + int total_sad_count = 0; 3312 3312 int mnl; 3313 3313 int dbl; 3314 3314 ··· 3322 3322 3323 3323 name = NULL; 3324 3324 drm_for_each_detailed_block((u8 *)edid, monitor_name, &name); 3325 + /* max: 13 bytes EDID, 16 bytes ELD */ 3325 3326 for (mnl = 0; name && mnl < 13; mnl++) { 3326 3327 if (name[mnl] == 0x0a) 3327 3328 break; ··· 3351 3350 dbl = cea_db_payload_len(db); 3352 3351 3353 3352 switch (cea_db_tag(db)) { 3353 + int sad_count; 3354 + 3354 3355 case AUDIO_BLOCK: 3355 3356 /* Audio Data Block, contains SADs */ 3356 - sad_count = dbl / 3; 3357 - if (dbl >= 1) 3358 - memcpy(eld + 20 + mnl, &db[1], dbl); 3357 + sad_count = min(dbl / 3, 15 - total_sad_count); 3358 + if (sad_count >= 1) 3359 + memcpy(eld + 20 + mnl + total_sad_count * 3, 3360 + &db[1], sad_count * 3); 3361 + total_sad_count += sad_count; 3359 3362 break; 3360 3363 case SPEAKER_BLOCK: 3361 3364 /* Speaker Allocation Data Block */ ··· 3376 3371 } 3377 3372 } 3378 3373 } 3379 - eld[5] |= sad_count << 4; 3374 + eld[5] |= total_sad_count << 4; 3380 3375 3381 3376 eld[DRM_ELD_BASELINE_ELD_LEN] = 3382 3377 DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4); 3383 3378 3384 3379 DRM_DEBUG_KMS("ELD size %d, SAD count %d\n", 3385 - drm_eld_size(eld), sad_count); 3380 + drm_eld_size(eld), total_sad_count); 3386 3381 } 3387 3382 EXPORT_SYMBOL(drm_edid_to_eld); 3388 3383
-8
drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c
··· 62 62 DCU_UPDATE_MODE_READREG); 63 63 } 64 64 65 - static bool fsl_dcu_drm_crtc_mode_fixup(struct drm_crtc *crtc, 66 - const struct drm_display_mode *mode, 67 - struct drm_display_mode *adjusted_mode) 68 - { 69 - return true; 70 - } 71 - 72 65 static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) 73 66 { 74 67 struct drm_device *dev = crtc->dev; ··· 120 127 .atomic_flush = fsl_dcu_drm_crtc_atomic_flush, 121 128 .disable = fsl_dcu_drm_disable_crtc, 122 129 .enable = fsl_dcu_drm_crtc_enable, 123 - .mode_fixup = fsl_dcu_drm_crtc_mode_fixup, 124 130 .mode_set_nofb = fsl_dcu_drm_crtc_mode_set_nofb, 125 131 }; 126 132
+6 -7
drivers/gpu/drm/gma500/cdv_intel_display.c
··· 116 116 .p1 = {.min = 1, .max = 10}, 117 117 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 10}, 118 118 .find_pll = cdv_intel_find_dp_pll, 119 - } 119 + } 120 120 }; 121 121 122 122 #define _wait_for(COND, MS, W) ({ \ ··· 245 245 /* We don't know what the other fields of these regs are, so 246 246 * leave them in place. 247 247 */ 248 - /* 248 + /* 249 249 * The BIT 14:13 of 0x8010/0x8030 is used to select the ref clk 250 250 * for the pipe A/B. Display spec 1.06 has wrong definition. 251 251 * Correct definition is like below: ··· 256 256 * 257 257 * if DPLLA sets 01 and DPLLB sets 02, both use clk from DPLLA 258 258 * 259 - */ 259 + */ 260 260 ret = cdv_sb_read(dev, ref_sfr, &ref_value); 261 261 if (ret) 262 262 return ret; ··· 646 646 * for DP/eDP. When using SSC clock, the ref clk is 100MHz.Otherwise 647 647 * it will be 27MHz. From the VBIOS code it seems that the pipe A choose 648 648 * 27MHz for DP/eDP while the Pipe B chooses the 100MHz. 649 - */ 649 + */ 650 650 if (pipe == 0) 651 651 refclk = 27000; 652 652 else ··· 659 659 } 660 660 661 661 drm_mode_debug_printmodeline(adjusted_mode); 662 - 662 + 663 663 limit = gma_crtc->clock_funcs->limit(crtc, refclk); 664 664 665 665 ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, ··· 721 721 pipeconf |= PIPE_6BPC; 722 722 } else 723 723 pipeconf |= PIPE_8BPC; 724 - 724 + 725 725 /* Set up the display plane register */ 726 726 dspcntr = DISPPLANE_GAMMA_ENABLE; 727 727 ··· 974 974 975 975 const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = { 976 976 .dpms = gma_crtc_dpms, 977 - .mode_fixup = gma_crtc_mode_fixup, 978 977 .mode_set = cdv_intel_crtc_mode_set, 979 978 .mode_set_base = gma_pipe_set_base, 980 979 .prepare = gma_crtc_prepare,
-7
drivers/gpu/drm/gma500/gma_display.c
··· 478 478 return 0; 479 479 } 480 480 481 - bool gma_crtc_mode_fixup(struct drm_crtc *crtc, 482 - const struct drm_display_mode *mode, 483 - struct drm_display_mode *adjusted_mode) 484 - { 485 - return true; 486 - } 487 - 488 481 void gma_crtc_prepare(struct drm_crtc *crtc) 489 482 { 490 483 const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
-3
drivers/gpu/drm/gma500/gma_display.h
··· 75 75 extern void gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, 76 76 u16 *blue, u32 start, u32 size); 77 77 extern void gma_crtc_dpms(struct drm_crtc *crtc, int mode); 78 - extern bool gma_crtc_mode_fixup(struct drm_crtc *crtc, 79 - const struct drm_display_mode *mode, 80 - struct drm_display_mode *adjusted_mode); 81 78 extern void gma_crtc_prepare(struct drm_crtc *crtc); 82 79 extern void gma_crtc_commit(struct drm_crtc *crtc); 83 80 extern void gma_crtc_disable(struct drm_crtc *crtc);
-2
drivers/gpu/drm/gma500/mdfld_intel_display.c
··· 1026 1026 1027 1027 const struct drm_crtc_helper_funcs mdfld_helper_funcs = { 1028 1028 .dpms = mdfld_crtc_dpms, 1029 - .mode_fixup = gma_crtc_mode_fixup, 1030 1029 .mode_set = mdfld_crtc_mode_set, 1031 1030 .mode_set_base = mdfld__intel_pipe_set_base, 1032 1031 .prepare = gma_crtc_prepare, 1033 1032 .commit = gma_crtc_commit, 1034 1033 }; 1035 -
-1
drivers/gpu/drm/gma500/oaktrail_crtc.c
··· 657 657 658 658 const struct drm_crtc_helper_funcs oaktrail_helper_funcs = { 659 659 .dpms = oaktrail_crtc_dpms, 660 - .mode_fixup = gma_crtc_mode_fixup, 661 660 .mode_set = oaktrail_crtc_mode_set, 662 661 .mode_set_base = oaktrail_pipe_set_base, 663 662 .prepare = gma_crtc_prepare,
-1
drivers/gpu/drm/gma500/psb_intel_display.c
··· 430 430 431 431 const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { 432 432 .dpms = gma_crtc_dpms, 433 - .mode_fixup = gma_crtc_mode_fixup, 434 433 .mode_set = psb_intel_crtc_mode_set, 435 434 .mode_set_base = gma_pipe_set_base, 436 435 .prepare = gma_crtc_prepare,
-13
drivers/gpu/drm/mgag200/mgag200_mode.c
··· 92 92 } while ((status & 0x01) && time_before(jiffies, timeout)); 93 93 } 94 94 95 - /* 96 - * The core passes the desired mode to the CRTC code to see whether any 97 - * CRTC-specific modifications need to be made to it. We're in a position 98 - * to just pass that straight through, so this does nothing 99 - */ 100 - static bool mga_crtc_mode_fixup(struct drm_crtc *crtc, 101 - const struct drm_display_mode *mode, 102 - struct drm_display_mode *adjusted_mode) 103 - { 104 - return true; 105 - } 106 - 107 95 #define P_ARRAY_SIZE 9 108 96 109 97 static int mga_g200se_set_plls(struct mga_device *mdev, long clock) ··· 1398 1410 static const struct drm_crtc_helper_funcs mga_helper_funcs = { 1399 1411 .disable = mga_crtc_disable, 1400 1412 .dpms = mga_crtc_dpms, 1401 - .mode_fixup = mga_crtc_mode_fixup, 1402 1413 .mode_set = mga_crtc_mode_set, 1403 1414 .mode_set_base = mga_crtc_mode_set_base, 1404 1415 .prepare = mga_crtc_prepare,
-8
drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
··· 147 147 kfree(mdp4_crtc); 148 148 } 149 149 150 - static bool mdp4_crtc_mode_fixup(struct drm_crtc *crtc, 151 - const struct drm_display_mode *mode, 152 - struct drm_display_mode *adjusted_mode) 153 - { 154 - return true; 155 - } 156 - 157 150 /* statically (for now) map planes to mixer stage (z-order): */ 158 151 static const int idxs[] = { 159 152 [VG1] = 1, ··· 494 501 }; 495 502 496 503 static const struct drm_crtc_helper_funcs mdp4_crtc_helper_funcs = { 497 - .mode_fixup = mdp4_crtc_mode_fixup, 498 504 .mode_set_nofb = mdp4_crtc_mode_set_nofb, 499 505 .disable = mdp4_crtc_disable, 500 506 .enable = mdp4_crtc_enable,
-8
drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
··· 185 185 kfree(mdp5_crtc); 186 186 } 187 187 188 - static bool mdp5_crtc_mode_fixup(struct drm_crtc *crtc, 189 - const struct drm_display_mode *mode, 190 - struct drm_display_mode *adjusted_mode) 191 - { 192 - return true; 193 - } 194 - 195 188 /* 196 189 * blend_setup() - blend all the planes of a CRTC 197 190 * ··· 620 627 }; 621 628 622 629 static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { 623 - .mode_fixup = mdp5_crtc_mode_fixup, 624 630 .mode_set_nofb = mdp5_crtc_mode_set_nofb, 625 631 .disable = mdp5_crtc_disable, 626 632 .enable = mdp5_crtc_enable,
-8
drivers/gpu/drm/nouveau/dispnv04/crtc.c
··· 227 227 NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); 228 228 } 229 229 230 - static bool 231 - nv_crtc_mode_fixup(struct drm_crtc *crtc, const struct drm_display_mode *mode, 232 - struct drm_display_mode *adjusted_mode) 233 - { 234 - return true; 235 - } 236 - 237 230 static void 238 231 nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) 239 232 { ··· 1086 1093 .dpms = nv_crtc_dpms, 1087 1094 .prepare = nv_crtc_prepare, 1088 1095 .commit = nv_crtc_commit, 1089 - .mode_fixup = nv_crtc_mode_fixup, 1090 1096 .mode_set = nv_crtc_mode_set, 1091 1097 .mode_set_base = nv04_crtc_mode_set_base, 1092 1098 .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
-8
drivers/gpu/drm/omapdrm/omap_crtc.c
··· 332 332 kfree(omap_crtc); 333 333 } 334 334 335 - static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, 336 - const struct drm_display_mode *mode, 337 - struct drm_display_mode *adjusted_mode) 338 - { 339 - return true; 340 - } 341 - 342 335 static void omap_crtc_enable(struct drm_crtc *crtc) 343 336 { 344 337 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); ··· 468 475 }; 469 476 470 477 static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { 471 - .mode_fixup = omap_crtc_mode_fixup, 472 478 .mode_set_nofb = omap_crtc_mode_set_nofb, 473 479 .disable = omap_crtc_disable, 474 480 .enable = omap_crtc_enable,
-9
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
··· 491 491 rcrtc->outputs = 0; 492 492 } 493 493 494 - static bool rcar_du_crtc_mode_fixup(struct drm_crtc *crtc, 495 - const struct drm_display_mode *mode, 496 - struct drm_display_mode *adjusted_mode) 497 - { 498 - /* TODO Fixup modes */ 499 - return true; 500 - } 501 - 502 494 static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc, 503 495 struct drm_crtc_state *old_crtc_state) 504 496 { ··· 523 531 } 524 532 525 533 static const struct drm_crtc_helper_funcs crtc_helper_funcs = { 526 - .mode_fixup = rcar_du_crtc_mode_fixup, 527 534 .disable = rcar_du_crtc_disable, 528 535 .enable = rcar_du_crtc_enable, 529 536 .atomic_begin = rcar_du_crtc_atomic_begin,
-8
drivers/gpu/drm/shmobile/shmob_drm_crtc.c
··· 359 359 scrtc->dpms = mode; 360 360 } 361 361 362 - static bool shmob_drm_crtc_mode_fixup(struct drm_crtc *crtc, 363 - const struct drm_display_mode *mode, 364 - struct drm_display_mode *adjusted_mode) 365 - { 366 - return true; 367 - } 368 - 369 362 static void shmob_drm_crtc_mode_prepare(struct drm_crtc *crtc) 370 363 { 371 364 shmob_drm_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); ··· 424 431 425 432 static const struct drm_crtc_helper_funcs crtc_helper_funcs = { 426 433 .dpms = shmob_drm_crtc_dpms, 427 - .mode_fixup = shmob_drm_crtc_mode_fixup, 428 434 .prepare = shmob_drm_crtc_mode_prepare, 429 435 .commit = shmob_drm_crtc_mode_commit, 430 436 .mode_set = shmob_drm_crtc_mode_set,
-9
drivers/gpu/drm/sti/sti_crtc.c
··· 51 51 mixer->status = STI_MIXER_DISABLING; 52 52 } 53 53 54 - static bool sti_crtc_mode_fixup(struct drm_crtc *crtc, 55 - const struct drm_display_mode *mode, 56 - struct drm_display_mode *adjusted_mode) 57 - { 58 - /* accept the provided drm_display_mode, do not fix it up */ 59 - return true; 60 - } 61 - 62 54 static int 63 55 sti_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode) 64 56 { ··· 221 229 static const struct drm_crtc_helper_funcs sti_crtc_helper_funcs = { 222 230 .enable = sti_crtc_enable, 223 231 .disable = sti_crtc_disabling, 224 - .mode_fixup = sti_crtc_mode_fixup, 225 232 .mode_set = drm_helper_crtc_mode_set, 226 233 .mode_set_nofb = sti_crtc_mode_set_nofb, 227 234 .mode_set_base = drm_helper_crtc_mode_set_base,
-9
drivers/gpu/drm/udl/udl_modeset.c
··· 279 279 280 280 } 281 281 282 - static bool udl_crtc_mode_fixup(struct drm_crtc *crtc, 283 - const struct drm_display_mode *mode, 284 - struct drm_display_mode *adjusted_mode) 285 - 286 - { 287 - return true; 288 - } 289 - 290 282 #if 0 291 283 static int 292 284 udl_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb, ··· 394 402 395 403 static const struct drm_crtc_helper_funcs udl_helper_funcs = { 396 404 .dpms = udl_crtc_dpms, 397 - .mode_fixup = udl_crtc_mode_fixup, 398 405 .mode_set = udl_crtc_mode_set, 399 406 .prepare = udl_crtc_prepare, 400 407 .commit = udl_crtc_commit,
-8
drivers/gpu/drm/virtio/virtgpu_display.c
··· 237 237 return 0; 238 238 } 239 239 240 - static bool virtio_gpu_crtc_mode_fixup(struct drm_crtc *crtc, 241 - const struct drm_display_mode *mode, 242 - struct drm_display_mode *adjusted_mode) 243 - { 244 - return true; 245 - } 246 - 247 240 static void virtio_gpu_crtc_mode_set_nofb(struct drm_crtc *crtc) 248 241 { 249 242 struct drm_device *dev = crtc->dev; ··· 270 277 static const struct drm_crtc_helper_funcs virtio_gpu_crtc_helper_funcs = { 271 278 .enable = virtio_gpu_crtc_enable, 272 279 .disable = virtio_gpu_crtc_disable, 273 - .mode_fixup = virtio_gpu_crtc_mode_fixup, 274 280 .mode_set_nofb = virtio_gpu_crtc_mode_set_nofb, 275 281 .atomic_check = virtio_gpu_crtc_atomic_check, 276 282 };
+3
include/drm/drm_atomic_helper.h
··· 146 146 struct drm_connector_state *state); 147 147 void drm_atomic_helper_connector_destroy_state(struct drm_connector *connector, 148 148 struct drm_connector_state *state); 149 + void drm_atomic_helper_legacy_gamma_set(struct drm_crtc *crtc, 150 + u16 *red, u16 *green, u16 *blue, 151 + uint32_t start, uint32_t size); 149 152 150 153 /** 151 154 * drm_atomic_crtc_for_each_plane - iterate over planes currently attached to CRTC
+47 -1
include/drm/drm_crtc.h
··· 305 305 * @mode_changed: crtc_state->mode or crtc_state->enable has been changed 306 306 * @active_changed: crtc_state->active has been toggled. 307 307 * @connectors_changed: connectors to this crtc have been updated 308 + * @color_mgmt_changed: color management properties have changed (degamma or 309 + * gamma LUT or CSC matrix) 308 310 * @plane_mask: bitmask of (1 << drm_plane_index(plane)) of attached planes 309 311 * @connector_mask: bitmask of (1 << drm_connector_index(connector)) of attached connectors 310 312 * @encoder_mask: bitmask of (1 << drm_encoder_index(encoder)) of attached encoders ··· 314 312 * update to ensure framebuffer cleanup isn't done too early 315 313 * @adjusted_mode: for use by helpers and drivers to compute adjusted mode timings 316 314 * @mode: current mode timings 315 + * @degamma_lut: Lookup table for converting framebuffer pixel data 316 + * before apply the conversion matrix 317 + * @ctm: Transformation matrix 318 + * @gamma_lut: Lookup table for converting pixel data after the 319 + * conversion matrix 317 320 * @event: optional pointer to a DRM event to signal upon completion of the 318 321 * state update 319 322 * @state: backpointer to global drm_atomic_state ··· 340 333 bool mode_changed : 1; 341 334 bool active_changed : 1; 342 335 bool connectors_changed : 1; 336 + bool color_mgmt_changed : 1; 343 337 344 338 /* attached planes bitmask: 345 339 * WARNING: transitional helpers do not maintain plane_mask so ··· 362 354 363 355 /* blob property to expose current mode to atomic userspace */ 364 356 struct drm_property_blob *mode_blob; 357 + 358 + /* blob property to expose color management to userspace */ 359 + struct drm_property_blob *degamma_lut; 360 + struct drm_property_blob *ctm; 361 + struct drm_property_blob *gamma_lut; 365 362 366 363 struct drm_pending_vblank_event *event; 367 364 ··· 770 757 int x, y; 771 758 const struct drm_crtc_funcs *funcs; 772 759 773 - /* CRTC gamma size for reporting to userspace */ 760 + /* Legacy FB CRTC gamma size for reporting to userspace */ 774 761 uint32_t gamma_size; 775 762 uint16_t *gamma_store; 776 763 ··· 1690 1677 * @dev: parent DRM device 1691 1678 * @allow_modeset: allow full modeset 1692 1679 * @legacy_cursor_update: hint to enforce legacy cursor IOCTL semantics 1680 + * @legacy_set_config: Disable conflicting encoders instead of failing with -EINVAL. 1693 1681 * @planes: pointer to array of plane pointers 1694 1682 * @plane_states: pointer to array of plane states pointers 1695 1683 * @crtcs: pointer to array of CRTC pointers ··· 1704 1690 struct drm_device *dev; 1705 1691 bool allow_modeset : 1; 1706 1692 bool legacy_cursor_update : 1; 1693 + bool legacy_set_config : 1; 1707 1694 struct drm_plane **planes; 1708 1695 struct drm_plane_state **plane_states; 1709 1696 struct drm_crtc **crtcs; ··· 2041 2026 * @property_blob_list: list of all the blob property objects 2042 2027 * @blob_lock: mutex for blob property allocation and management 2043 2028 * @*_property: core property tracking 2029 + * @degamma_lut_property: LUT used to convert the framebuffer's colors to linear 2030 + * gamma 2031 + * @degamma_lut_size_property: size of the degamma LUT as supported by the 2032 + * driver (read-only) 2033 + * @ctm_property: Matrix used to convert colors after the lookup in the 2034 + * degamma LUT 2035 + * @gamma_lut_property: LUT used to convert the colors, after the CSC matrix, to 2036 + * the gamma space of the connected screen (read-only) 2037 + * @gamma_lut_size_property: size of the gamma LUT as supported by the driver 2044 2038 * @preferred_depth: preferred RBG pixel depth, used by fb helpers 2045 2039 * @prefer_shadow: hint to userspace to prefer shadow-fb rendering 2046 2040 * @async_page_flip: does this device support async flips on the primary plane? ··· 2151 2127 struct drm_property *scaling_mode_property; 2152 2128 struct drm_property *aspect_ratio_property; 2153 2129 struct drm_property *dirty_info_property; 2130 + 2131 + /* Optional color correction properties */ 2132 + struct drm_property *degamma_lut_property; 2133 + struct drm_property *degamma_lut_size_property; 2134 + struct drm_property *ctm_property; 2135 + struct drm_property *gamma_lut_property; 2136 + struct drm_property *gamma_lut_size_property; 2154 2137 2155 2138 /* properties for virtual machine layout */ 2156 2139 struct drm_property *suggested_x_property; ··· 2583 2552 struct drm_mode_object *mo; 2584 2553 mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY); 2585 2554 return mo ? obj_to_property(mo) : NULL; 2555 + } 2556 + 2557 + /* 2558 + * Extract a degamma/gamma LUT value provided by user and round it to the 2559 + * precision supported by the hardware. 2560 + */ 2561 + static inline uint32_t drm_color_lut_extract(uint32_t user_input, 2562 + uint32_t bit_precision) 2563 + { 2564 + uint32_t val = user_input + (1 << (16 - bit_precision - 1)); 2565 + uint32_t max = 0xffff >> (16 - bit_precision); 2566 + 2567 + val >>= 16 - bit_precision; 2568 + 2569 + return clamp_val(val, 0, max); 2586 2570 } 2587 2571 2588 2572 /* Plane list iterator for legacy (overlay only) planes. */
+3
include/drm/drm_crtc_helper.h
··· 48 48 struct drm_display_mode *mode, 49 49 int x, int y, 50 50 struct drm_framebuffer *old_fb); 51 + extern void drm_helper_crtc_enable_color_mgmt(struct drm_crtc *crtc, 52 + int degamma_lut_size, 53 + int gamma_lut_size); 51 54 extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc); 52 55 extern bool drm_helper_encoder_in_use(struct drm_encoder *encoder); 53 56
+15
include/uapi/drm/drm_mode.h
··· 487 487 __u64 blue; 488 488 }; 489 489 490 + struct drm_color_ctm { 491 + /* Conversion matrix in S31.32 format. */ 492 + __s64 matrix[9]; 493 + }; 494 + 495 + struct drm_color_lut { 496 + /* 497 + * Data is U0.16 fixed point format. 498 + */ 499 + __u16 red; 500 + __u16 green; 501 + __u16 blue; 502 + __u16 reserved; 503 + }; 504 + 490 505 #define DRM_MODE_PAGE_FLIP_EVENT 0x01 491 506 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 492 507 #define DRM_MODE_PAGE_FLIP_FLAGS (DRM_MODE_PAGE_FLIP_EVENT|DRM_MODE_PAGE_FLIP_ASYNC)