You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'drm-misc-next-2017-06-02' of git://anongit.freedesktop.org/git/drm-misc into drm-next
Core Changes: - Stop proliferation of drm_vblank_cleanup by adding to the docs and deleting boilerplate (Daniel) - Roll out and use mode_valid hooks across crtc/encoder/bridge (Jose) - Add drm_vblank.[hc] to isolate vblank code from optional irq helpers (Daniel) Driver Changes: - Replace drm_for_each_connector with drm_for_each_connector_iter (Gustavo) - A couple misc driver fixes Cc: Gustavo Padovan <gustavo.padovan@collabora.com> Cc: Jose Abreu <Jose.Abreu@synopsys.com> Cc: Daniel Vetter <daniel.vetter@intel.com> * tag 'drm-misc-next-2017-06-02' of git://anongit.freedesktop.org/git/drm-misc: (34 commits) drm/vc4: Mark the device as active when enabling runtime PM. drm: remove writeq/readq function definitions drm/atmel-hlcdc: Use crtc->mode_valid() callback drm/exynos: Drop drm_vblank_cleanup drm/hdlcd|mali: Drop drm_vblank_cleanup drm/doc: Polish irq helper documentation drm: Extract drm_vblank.[hc] drm/vc4: Fix comment in vc4_drv.h drm/pl111: fix warnings without CONFIG_ARM_AMBA drm/atomic: Consitfy mode parameter to drm_atomic_set_mode_for_crtc() drm/arcgpu: Drop drm_vblank_cleanup drm/atmel: Drop drm_vblank_cleanup drm/imx: Drop drm_vblank_cleanup drm/meson: Drop drm_vblank_cleanup drm/stm: Drop drm_vblank_cleanup drm/sun4i: Drop drm_vblank_cleanup drm: better document how to send out the crtc disable event drm: Use vsnprintf extension %ph drm/doc: move printf helpers out of drmP.h drm/pl111: select DRM_PANEL ...
This commit is contained in:
@@ -149,60 +149,15 @@ Device Instance and Driver Handling
|
||||
Driver Load
|
||||
-----------
|
||||
|
||||
IRQ Registration
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The DRM core tries to facilitate IRQ handler registration and
|
||||
unregistration by providing :c:func:`drm_irq_install()` and
|
||||
:c:func:`drm_irq_uninstall()` functions. Those functions only
|
||||
support a single interrupt per device, devices that use more than one
|
||||
IRQs need to be handled manually.
|
||||
IRQ Helper Library
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Managed IRQ Registration
|
||||
''''''''''''''''''''''''
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_irq.c
|
||||
:doc: irq helpers
|
||||
|
||||
:c:func:`drm_irq_install()` starts by calling the irq_preinstall
|
||||
driver operation. The operation is optional and must make sure that the
|
||||
interrupt will not get fired by clearing all pending interrupt flags or
|
||||
disabling the interrupt.
|
||||
|
||||
The passed-in IRQ will then be requested by a call to
|
||||
:c:func:`request_irq()`. If the DRIVER_IRQ_SHARED driver feature
|
||||
flag is set, a shared (IRQF_SHARED) IRQ handler will be requested.
|
||||
|
||||
The IRQ handler function must be provided as the mandatory irq_handler
|
||||
driver operation. It will get passed directly to
|
||||
:c:func:`request_irq()` and thus has the same prototype as all IRQ
|
||||
handlers. It will get called with a pointer to the DRM device as the
|
||||
second argument.
|
||||
|
||||
Finally the function calls the optional irq_postinstall driver
|
||||
operation. The operation usually enables interrupts (excluding the
|
||||
vblank interrupt, which is enabled separately), but drivers may choose
|
||||
to enable/disable interrupts at a different time.
|
||||
|
||||
:c:func:`drm_irq_uninstall()` is similarly used to uninstall an
|
||||
IRQ handler. It starts by waking up all processes waiting on a vblank
|
||||
interrupt to make sure they don't hang, and then calls the optional
|
||||
irq_uninstall driver operation. The operation must disable all hardware
|
||||
interrupts. Finally the function frees the IRQ by calling
|
||||
:c:func:`free_irq()`.
|
||||
|
||||
Manual IRQ Registration
|
||||
'''''''''''''''''''''''
|
||||
|
||||
Drivers that require multiple interrupt handlers can't use the managed
|
||||
IRQ registration functions. In that case IRQs must be registered and
|
||||
unregistered manually (usually with the :c:func:`request_irq()` and
|
||||
:c:func:`free_irq()` functions, or their :c:func:`devm_request_irq()` and
|
||||
:c:func:`devm_free_irq()` equivalents).
|
||||
|
||||
When manually registering IRQs, drivers must not set the
|
||||
DRIVER_HAVE_IRQ driver feature flag, and must not provide the
|
||||
irq_handler driver operation. They must set the :c:type:`struct
|
||||
drm_device <drm_device>` irq_enabled field to 1 upon
|
||||
registration of the IRQs, and clear it to 0 after unregistering the
|
||||
IRQs.
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_irq.c
|
||||
:export:
|
||||
|
||||
Memory Manager Initialization
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -612,8 +612,8 @@ operation handler.
|
||||
Vertical Blanking and Interrupt Handling Functions Reference
|
||||
------------------------------------------------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_irq.h
|
||||
.. kernel-doc:: include/drm/drm_vblank.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_irq.c
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_vblank.c
|
||||
:export:
|
||||
|
||||
@@ -177,19 +177,6 @@ following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and
|
||||
|
||||
Contact: Daniel Vetter, respective driver maintainers
|
||||
|
||||
Switch to drm_connector_list_iter for any connector_list walking
|
||||
----------------------------------------------------------------
|
||||
|
||||
Connectors can be hotplugged, and we now have a special list of helpers to walk
|
||||
the connector_list in a race-free fashion, without incurring deadlocks on
|
||||
mutexes and other fun stuff.
|
||||
|
||||
Unfortunately most drivers are not converted yet. At least all those supporting
|
||||
DP MST hotplug should be converted, since for those drivers the difference
|
||||
matters. See drm_for_each_connector_iter() vs. drm_for_each_connector().
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
|
||||
drm_framebuffer.o drm_connector.o drm_blend.o \
|
||||
drm_encoder.o drm_mode_object.o drm_property.o \
|
||||
drm_plane.o drm_color_mgmt.o drm_print.o \
|
||||
drm_dumb_buffers.o drm_mode_config.o
|
||||
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o
|
||||
|
||||
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
|
||||
drm-$(CONFIG_DRM_VM) += drm_vm.o
|
||||
|
||||
@@ -155,7 +155,6 @@ static int arcpgu_unload(struct drm_device *drm)
|
||||
arcpgu->fbdev = NULL;
|
||||
}
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_vblank_cleanup(drm);
|
||||
drm_mode_config_cleanup(drm);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -340,7 +340,6 @@ err_register:
|
||||
}
|
||||
err_fbdev:
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
drm_vblank_cleanup(drm);
|
||||
err_vblank:
|
||||
pm_runtime_disable(drm->dev);
|
||||
err_pm_active:
|
||||
@@ -368,7 +367,6 @@ static void hdlcd_drm_unbind(struct device *dev)
|
||||
}
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
component_unbind_all(dev, drm);
|
||||
drm_vblank_cleanup(drm);
|
||||
pm_runtime_get_sync(drm->dev);
|
||||
drm_irq_uninstall(drm);
|
||||
pm_runtime_put_sync(drm->dev);
|
||||
|
||||
@@ -652,7 +652,6 @@ register_fail:
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
fbdev_fail:
|
||||
pm_runtime_get_sync(dev);
|
||||
drm_vblank_cleanup(drm);
|
||||
vblank_fail:
|
||||
malidp_se_irq_fini(drm);
|
||||
malidp_de_irq_fini(drm);
|
||||
@@ -692,7 +691,6 @@ static void malidp_unbind(struct device *dev)
|
||||
}
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
pm_runtime_get_sync(dev);
|
||||
drm_vblank_cleanup(drm);
|
||||
malidp_se_irq_fini(drm);
|
||||
malidp_de_irq_fini(drm);
|
||||
component_unbind_all(dev, drm);
|
||||
|
||||
@@ -140,13 +140,13 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
|
||||
cfg);
|
||||
}
|
||||
|
||||
static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *c,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
static enum drm_mode_status
|
||||
atmel_hlcdc_crtc_mode_valid(struct drm_crtc *c,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
|
||||
|
||||
return atmel_hlcdc_dc_mode_valid(crtc->dc, adjusted_mode) == MODE_OK;
|
||||
return atmel_hlcdc_dc_mode_valid(crtc->dc, mode);
|
||||
}
|
||||
|
||||
static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
|
||||
@@ -315,7 +315,7 @@ 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_valid = atmel_hlcdc_crtc_mode_valid,
|
||||
.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,
|
||||
|
||||
@@ -375,8 +375,9 @@ static const struct of_device_id atmel_hlcdc_of_match[] = {
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, atmel_hlcdc_of_match);
|
||||
|
||||
int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
|
||||
struct drm_display_mode *mode)
|
||||
enum drm_mode_status
|
||||
atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
int vfront_porch = mode->vsync_start - mode->vdisplay;
|
||||
int vback_porch = mode->vtotal - mode->vsync_end;
|
||||
@@ -678,7 +679,6 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
|
||||
flush_workqueue(dc->wq);
|
||||
drm_kms_helper_poll_fini(dev);
|
||||
drm_mode_config_cleanup(dev);
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
pm_runtime_get_sync(dev->dev);
|
||||
drm_irq_uninstall(dev);
|
||||
|
||||
@@ -422,8 +422,9 @@ static inline void atmel_hlcdc_layer_init(struct atmel_hlcdc_layer *layer,
|
||||
layer->regmap = regmap;
|
||||
}
|
||||
|
||||
int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
|
||||
struct drm_display_mode *mode);
|
||||
enum drm_mode_status
|
||||
atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
|
||||
const struct drm_display_mode *mode);
|
||||
|
||||
int atmel_hlcdc_create_planes(struct drm_device *dev);
|
||||
void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane);
|
||||
|
||||
@@ -1061,18 +1061,18 @@ static int anx78xx_bridge_attach(struct drm_bridge *bridge)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool anx78xx_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
static enum drm_mode_status
|
||||
anx78xx_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
|
||||
return false;
|
||||
return MODE_NO_INTERLACE;
|
||||
|
||||
/* Max 1200p at 5.4 Ghz, one lane */
|
||||
if (mode->clock > 154000)
|
||||
return false;
|
||||
return MODE_CLOCK_HIGH;
|
||||
|
||||
return true;
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static void anx78xx_bridge_disable(struct drm_bridge *bridge)
|
||||
@@ -1129,7 +1129,7 @@ static void anx78xx_bridge_enable(struct drm_bridge *bridge)
|
||||
|
||||
static const struct drm_bridge_funcs anx78xx_bridge_funcs = {
|
||||
.attach = anx78xx_bridge_attach,
|
||||
.mode_fixup = anx78xx_bridge_mode_fixup,
|
||||
.mode_valid = anx78xx_bridge_mode_valid,
|
||||
.disable = anx78xx_bridge_disable,
|
||||
.mode_set = anx78xx_bridge_mode_set,
|
||||
.enable = anx78xx_bridge_enable,
|
||||
|
||||
@@ -328,7 +328,7 @@ static s32 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
|
||||
* Zero on success, error code on failure. Cannot return -EDEADLK.
|
||||
*/
|
||||
int drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
|
||||
struct drm_display_mode *mode)
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
struct drm_mode_modeinfo umode;
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <linux/dma-fence.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
/**
|
||||
@@ -452,6 +453,69 @@ mode_fixup(struct drm_atomic_state *state)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum drm_mode_status mode_valid_path(struct drm_connector *connector,
|
||||
struct drm_encoder *encoder,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
enum drm_mode_status ret;
|
||||
|
||||
ret = drm_encoder_mode_valid(encoder, mode);
|
||||
if (ret != MODE_OK) {
|
||||
DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] mode_valid() failed\n",
|
||||
encoder->base.id, encoder->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_bridge_mode_valid(encoder->bridge, mode);
|
||||
if (ret != MODE_OK) {
|
||||
DRM_DEBUG_ATOMIC("[BRIDGE] mode_valid() failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = drm_crtc_mode_valid(crtc, mode);
|
||||
if (ret != MODE_OK) {
|
||||
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] mode_valid() failed\n",
|
||||
crtc->base.id, crtc->name);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
mode_valid(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_connector_state *conn_state;
|
||||
struct drm_connector *connector;
|
||||
int i;
|
||||
|
||||
for_each_new_connector_in_state(state, connector, conn_state, i) {
|
||||
struct drm_encoder *encoder = conn_state->best_encoder;
|
||||
struct drm_crtc *crtc = conn_state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
enum drm_mode_status mode_status;
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
if (!crtc || !encoder)
|
||||
continue;
|
||||
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
|
||||
if (!crtc_state)
|
||||
continue;
|
||||
if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
|
||||
continue;
|
||||
|
||||
mode = &crtc_state->mode;
|
||||
|
||||
mode_status = mode_valid_path(connector, encoder, crtc, mode);
|
||||
if (mode_status != MODE_OK)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_atomic_helper_check_modeset - validate state object for modeset changes
|
||||
* @dev: DRM device
|
||||
@@ -466,13 +530,15 @@ mode_fixup(struct drm_atomic_state *state)
|
||||
* 2. &drm_connector_helper_funcs.atomic_check to validate the connector state.
|
||||
* 3. If it's determined a modeset is needed then all connectors on the affected crtc
|
||||
* crtc are added and &drm_connector_helper_funcs.atomic_check is run on them.
|
||||
* 4. &drm_bridge_funcs.mode_fixup is called on all encoder bridges.
|
||||
* 5. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state.
|
||||
* 4. &drm_encoder_helper_funcs.mode_valid, &drm_bridge_funcs.mode_valid and
|
||||
* &drm_crtc_helper_funcs.mode_valid are called on the affected components.
|
||||
* 5. &drm_bridge_funcs.mode_fixup is called on all encoder bridges.
|
||||
* 6. &drm_encoder_helper_funcs.atomic_check is called to validate any encoder state.
|
||||
* This function is only called when the encoder will be part of a configured crtc,
|
||||
* it must not be used for implementing connector property validation.
|
||||
* If this function is NULL, &drm_atomic_encoder_helper_funcs.mode_fixup is called
|
||||
* instead.
|
||||
* 6. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints.
|
||||
* 7. &drm_crtc_helper_funcs.mode_fixup is called last, to fix up the mode with crtc constraints.
|
||||
*
|
||||
* &drm_crtc_state.mode_changed is set when the input mode is changed.
|
||||
* &drm_crtc_state.connectors_changed is set when a connector is added or
|
||||
@@ -617,6 +683,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = mode_valid(state);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mode_fixup(state);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_atomic_helper_check_modeset);
|
||||
|
||||
@@ -205,6 +205,39 @@ bool drm_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_bridge_mode_fixup);
|
||||
|
||||
/**
|
||||
* drm_bridge_mode_valid - validate the mode against all bridges in the
|
||||
* encoder chain.
|
||||
* @bridge: bridge control structure
|
||||
* @mode: desired mode to be validated
|
||||
*
|
||||
* Calls &drm_bridge_funcs.mode_valid for all the bridges in the encoder
|
||||
* chain, starting from the first bridge to the last. If at least one bridge
|
||||
* does not accept the mode the function returns the error code.
|
||||
*
|
||||
* Note: the bridge passed should be the one closest to the encoder.
|
||||
*
|
||||
* RETURNS:
|
||||
* MODE_OK on success, drm_mode_status Enum error code on failure
|
||||
*/
|
||||
enum drm_mode_status drm_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
enum drm_mode_status ret = MODE_OK;
|
||||
|
||||
if (!bridge)
|
||||
return ret;
|
||||
|
||||
if (bridge->funcs->mode_valid)
|
||||
ret = bridge->funcs->mode_valid(bridge, mode);
|
||||
|
||||
if (ret != MODE_OK)
|
||||
return ret;
|
||||
|
||||
return drm_bridge_mode_valid(bridge->next, mode);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_bridge_mode_valid);
|
||||
|
||||
/**
|
||||
* drm_bridge_disable - disables all bridges in the encoder chain
|
||||
* @bridge: bridge control structure
|
||||
|
||||
@@ -26,7 +26,11 @@
|
||||
* implementation details and are not exported to drivers.
|
||||
*/
|
||||
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_modes.h>
|
||||
|
||||
/* drm_fb_helper.c */
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
@@ -63,3 +67,11 @@ static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* drm_probe_helper.c */
|
||||
enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode);
|
||||
enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
|
||||
const struct drm_display_mode *mode);
|
||||
enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
@@ -2836,16 +2836,15 @@ static void drm_dp_mst_dump_mstb(struct seq_file *m,
|
||||
static bool dump_dp_payload_table(struct drm_dp_mst_topology_mgr *mgr,
|
||||
char *buf)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_PAYLOAD_TABLE_UPDATE_STATUS + (i * 16), &buf[i * 16], 16);
|
||||
if (ret != 16)
|
||||
break;
|
||||
|
||||
for (i = 0; i < 64; i += 16) {
|
||||
if (drm_dp_dpcd_read(mgr->aux,
|
||||
DP_PAYLOAD_TABLE_UPDATE_STATUS + i,
|
||||
&buf[i], 16) != 16)
|
||||
return false;
|
||||
}
|
||||
if (i == 4)
|
||||
return true;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fetch_monitor_name(struct drm_dp_mst_topology_mgr *mgr,
|
||||
@@ -2909,42 +2908,24 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
|
||||
mutex_lock(&mgr->lock);
|
||||
if (mgr->mst_primary) {
|
||||
u8 buf[64];
|
||||
bool bret;
|
||||
int ret;
|
||||
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_DPCD_REV, buf, DP_RECEIVER_CAP_SIZE);
|
||||
seq_printf(m, "dpcd: ");
|
||||
for (i = 0; i < DP_RECEIVER_CAP_SIZE; i++)
|
||||
seq_printf(m, "%02x ", buf[i]);
|
||||
seq_printf(m, "\n");
|
||||
seq_printf(m, "dpcd: %*ph\n", DP_RECEIVER_CAP_SIZE, buf);
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2);
|
||||
seq_printf(m, "faux/mst: ");
|
||||
for (i = 0; i < 2; i++)
|
||||
seq_printf(m, "%02x ", buf[i]);
|
||||
seq_printf(m, "\n");
|
||||
seq_printf(m, "faux/mst: %*ph\n", 2, buf);
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1);
|
||||
seq_printf(m, "mst ctrl: ");
|
||||
for (i = 0; i < 1; i++)
|
||||
seq_printf(m, "%02x ", buf[i]);
|
||||
seq_printf(m, "\n");
|
||||
seq_printf(m, "mst ctrl: %*ph\n", 1, buf);
|
||||
|
||||
/* dump the standard OUI branch header */
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE);
|
||||
seq_printf(m, "branch oui: ");
|
||||
for (i = 0; i < 0x3; i++)
|
||||
seq_printf(m, "%02x", buf[i]);
|
||||
seq_printf(m, " devid: ");
|
||||
seq_printf(m, "branch oui: %*phN devid: ", 3, buf);
|
||||
for (i = 0x3; i < 0x8 && buf[i]; i++)
|
||||
seq_printf(m, "%c", buf[i]);
|
||||
|
||||
seq_printf(m, " revision: hw: %x.%x sw: %x.%x", buf[0x9] >> 4, buf[0x9] & 0xf, buf[0xa], buf[0xb]);
|
||||
seq_printf(m, "\n");
|
||||
bret = dump_dp_payload_table(mgr, buf);
|
||||
if (bret == true) {
|
||||
seq_printf(m, "payload table: ");
|
||||
for (i = 0; i < 63; i++)
|
||||
seq_printf(m, "%02x ", buf[i]);
|
||||
seq_printf(m, "\n");
|
||||
}
|
||||
seq_printf(m, " revision: hw: %x.%x sw: %x.%x\n",
|
||||
buf[0x9] >> 4, buf[0x9] & 0xf, buf[0xa], buf[0xb]);
|
||||
if (dump_dp_payload_table(mgr, buf))
|
||||
seq_printf(m, "payload table: %*ph\n", 63, buf);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -53,8 +53,9 @@ int drm_name_info(struct seq_file *m, void *data);
|
||||
int drm_clients_info(struct seq_file *m, void* data);
|
||||
int drm_gem_name_info(struct seq_file *m, void *data);
|
||||
|
||||
/* drm_irq.c */
|
||||
/* drm_vblank.c */
|
||||
extern unsigned int drm_timestamp_monotonic;
|
||||
void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe);
|
||||
|
||||
/* IOCTLS */
|
||||
int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
|
||||
+42
-1601
File diff suppressed because it is too large
Load Diff
@@ -38,6 +38,9 @@
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
|
||||
/**
|
||||
* DOC: output probing helper overview
|
||||
@@ -80,6 +83,61 @@ drm_mode_validate_flag(const struct drm_display_mode *mode,
|
||||
return MODE_OK;
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
drm_mode_validate_pipeline(struct drm_display_mode *mode,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
uint32_t *ids = connector->encoder_ids;
|
||||
enum drm_mode_status ret = MODE_OK;
|
||||
unsigned int i;
|
||||
|
||||
/* Step 1: Validate against connector */
|
||||
ret = drm_connector_mode_valid(connector, mode);
|
||||
if (ret != MODE_OK)
|
||||
return ret;
|
||||
|
||||
/* Step 2: Validate against encoders and crtcs */
|
||||
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
|
||||
struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
|
||||
struct drm_crtc *crtc;
|
||||
|
||||
if (!encoder)
|
||||
continue;
|
||||
|
||||
ret = drm_encoder_mode_valid(encoder, mode);
|
||||
if (ret != MODE_OK) {
|
||||
/* No point in continuing for crtc check as this encoder
|
||||
* will not accept the mode anyway. If all encoders
|
||||
* reject the mode then, at exit, ret will not be
|
||||
* MODE_OK. */
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = drm_bridge_mode_valid(encoder->bridge, mode);
|
||||
if (ret != MODE_OK) {
|
||||
/* There is also no point in continuing for crtc check
|
||||
* here. */
|
||||
continue;
|
||||
}
|
||||
|
||||
drm_for_each_crtc(crtc, dev) {
|
||||
if (!drm_encoder_crtc_ok(encoder, crtc))
|
||||
continue;
|
||||
|
||||
ret = drm_crtc_mode_valid(crtc, mode);
|
||||
if (ret == MODE_OK) {
|
||||
/* If we get to this point there is at least
|
||||
* one combination of encoder+crtc that works
|
||||
* for this mode. Lets return now. */
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_cmdline_mode *cmdline_mode;
|
||||
@@ -113,6 +171,41 @@ static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector)
|
||||
return 1;
|
||||
}
|
||||
|
||||
enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
|
||||
|
||||
if (!crtc_funcs || !crtc_funcs->mode_valid)
|
||||
return MODE_OK;
|
||||
|
||||
return crtc_funcs->mode_valid(crtc, mode);
|
||||
}
|
||||
|
||||
enum drm_mode_status drm_encoder_mode_valid(struct drm_encoder *encoder,
|
||||
const struct drm_display_mode *mode)
|
||||
{
|
||||
const struct drm_encoder_helper_funcs *encoder_funcs =
|
||||
encoder->helper_private;
|
||||
|
||||
if (!encoder_funcs || !encoder_funcs->mode_valid)
|
||||
return MODE_OK;
|
||||
|
||||
return encoder_funcs->mode_valid(encoder, mode);
|
||||
}
|
||||
|
||||
enum drm_mode_status drm_connector_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
const struct drm_connector_helper_funcs *connector_funcs =
|
||||
connector->helper_private;
|
||||
|
||||
if (!connector_funcs || !connector_funcs->mode_valid)
|
||||
return MODE_OK;
|
||||
|
||||
return connector_funcs->mode_valid(connector, mode);
|
||||
}
|
||||
|
||||
#define DRM_OUTPUT_POLL_PERIOD (10*HZ)
|
||||
/**
|
||||
* drm_kms_helper_poll_enable - re-enable output polling.
|
||||
@@ -284,7 +377,11 @@ EXPORT_SYMBOL(drm_helper_probe_detect);
|
||||
* - drm_mode_validate_flag() checks the modes against basic connector
|
||||
* capabilities (interlace_allowed,doublescan_allowed,stereo_allowed)
|
||||
* - the optional &drm_connector_helper_funcs.mode_valid helper can perform
|
||||
* driver and/or hardware specific checks
|
||||
* driver and/or sink specific checks
|
||||
* - the optional &drm_crtc_helper_funcs.mode_valid,
|
||||
* &drm_bridge_funcs.mode_valid and &drm_encoder_helper_funcs.mode_valid
|
||||
* helpers can perform driver and/or source specific checks which are also
|
||||
* enforced by the modeset/atomic helpers
|
||||
*
|
||||
* 5. Any mode whose status is not OK is pruned from the connector's modes list,
|
||||
* accompanied by a debug message indicating the reason for the mode's
|
||||
@@ -428,9 +525,9 @@ retry:
|
||||
if (mode->status == MODE_OK)
|
||||
mode->status = drm_mode_validate_flag(mode, mode_flags);
|
||||
|
||||
if (mode->status == MODE_OK && connector_funcs->mode_valid)
|
||||
mode->status = connector_funcs->mode_valid(connector,
|
||||
mode);
|
||||
if (mode->status == MODE_OK)
|
||||
mode->status = drm_mode_validate_pipeline(mode,
|
||||
connector);
|
||||
}
|
||||
|
||||
prune:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user