diff --git a/linux/0001-drm-fixes-when-i2c-encoder-slave-mode_fixup-is-null.patch b/linux/0001-drm-fixes-when-i2c-encoder-slave-mode_fixup-is-null.patch deleted file mode 100644 index 44e07c5e82f..00000000000 --- a/linux/0001-drm-fixes-when-i2c-encoder-slave-mode_fixup-is-null.patch +++ /dev/null @@ -1,33 +0,0 @@ -From c2fe3de556a40fb59fb157fc0ece18903030cfd6 Mon Sep 17 00:00:00 2001 -From: Carlos Palminha -Date: Wed, 10 Feb 2016 12:08:38 +0000 -Subject: [PATCH 1/9] drm: fixes when i2c encoder slave mode_fixup is null. - -Avoid i2c slave encoder drivers to copy/paste code to implement functions that will -only return true. - -Signed-off-by: Carlos Palminha -[danvet: whitespace requested by Jani.] -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/1455106118-32145-1-git-send-email-palminha@synopsys.com ---- - drivers/gpu/drm/drm_encoder_slave.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/drivers/gpu/drm/drm_encoder_slave.c b/drivers/gpu/drm/drm_encoder_slave.c -index d18b88b..d33a769 100644 ---- a/drivers/gpu/drm/drm_encoder_slave.c -+++ b/drivers/gpu/drm/drm_encoder_slave.c -@@ -140,6 +140,9 @@ bool drm_i2c_encoder_mode_fixup(struct drm_encoder *encoder, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) - { -+ if (!get_slave_funcs(encoder)->mode_fixup) -+ return true; -+ - return get_slave_funcs(encoder)->mode_fixup(encoder, mode, adjusted_mode); - } - EXPORT_SYMBOL(drm_i2c_encoder_mode_fixup); --- -2.5.5 - diff --git a/linux/0002-drm-fixes-crct-set_mode-when-encoder-mode_fixup-is-n.patch b/linux/0002-drm-fixes-crct-set_mode-when-encoder-mode_fixup-is-n.patch deleted file mode 100644 index bc38bd9671a..00000000000 --- a/linux/0002-drm-fixes-crct-set_mode-when-encoder-mode_fixup-is-n.patch +++ /dev/null @@ -1,975 +0,0 @@ -From 6c778f1fc5b2e2aab7ea70e92f5f2a6a7e5bdf45 Mon Sep 17 00:00:00 2001 -From: Carlos Palminha -Date: Wed, 10 Feb 2016 12:15:22 +0000 -Subject: [PATCH 2/9] drm: fixes crct set_mode when encoder mode_fixup is null. - -Avoids null crash when encoders don't implement mode_fixup. - -Signed-off-by: Carlos Palminha -[danvet: Also update kerneldoc.] -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/1455106522-32307-1-git-send-email-palminha@synopsys.com ---- - drivers/gpu/drm/drm_crtc_helper.c | 10 +- - include/drm/drm_modeset_helper_vtables.h | 928 +++++++++++++++++++++++++++++++ - 2 files changed, 934 insertions(+), 4 deletions(-) - create mode 100644 include/drm/drm_modeset_helper_vtables.h - -diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c -index ef53475..5becaa2 100644 ---- a/drivers/gpu/drm/drm_crtc_helper.c -+++ b/drivers/gpu/drm/drm_crtc_helper.c -@@ -318,10 +318,12 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, - } - - encoder_funcs = encoder->helper_private; -- if (!(ret = encoder_funcs->mode_fixup(encoder, mode, -- adjusted_mode))) { -- DRM_DEBUG_KMS("Encoder fixup failed\n"); -- goto done; -+ if (encoder_funcs->mode_fixup) { -+ if (!(ret = encoder_funcs->mode_fixup(encoder, mode, -+ adjusted_mode))) { -+ DRM_DEBUG_KMS("Encoder fixup failed\n"); -+ goto done; -+ } - } - } - -diff --git a/include/drm/drm_modeset_helper_vtables.h b/include/drm/drm_modeset_helper_vtables.h -new file mode 100644 -index 0000000..0e3b1d5 ---- /dev/null -+++ b/include/drm/drm_modeset_helper_vtables.h -@@ -0,0 +1,928 @@ -+/* -+ * Copyright © 2006 Keith Packard -+ * Copyright © 2007-2008 Dave Airlie -+ * Copyright © 2007-2008 Intel Corporation -+ * Jesse Barnes -+ * Copyright © 2011-2013 Intel Corporation -+ * Copyright © 2015 Intel Corporation -+ * Daniel Vetter -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR -+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef __DRM_MODESET_HELPER_VTABLES_H__ -+#define __DRM_MODESET_HELPER_VTABLES_H__ -+ -+#include -+ -+/** -+ * DOC: overview -+ * -+ * The DRM mode setting helper functions are common code for drivers to use if -+ * they wish. Drivers are not forced to use this code in their -+ * implementations but it would be useful if the code they do use at least -+ * provides a consistent interface and operation to userspace. Therefore it is -+ * highly recommended to use the provided helpers as much as possible. -+ * -+ * Because there is only one pointer per modeset object to hold a vfunc table -+ * for helper libraries they are by necessity shared among the different -+ * helpers. -+ * -+ * To make this clear all the helper vtables are pulled together in this location here. -+ */ -+ -+enum mode_set_atomic; -+ -+/** -+ * struct drm_crtc_helper_funcs - helper operations for CRTCs -+ * -+ * These hooks are used by the legacy CRTC helpers, the transitional plane -+ * helpers and the new atomic modesetting helpers. -+ */ -+struct drm_crtc_helper_funcs { -+ /** -+ * @dpms: -+ * -+ * Callback to control power levels on the CRTC. If the mode passed in -+ * is unsupported, the provider must use the next lowest power level. -+ * This is used by the legacy CRTC helpers to implement DPMS -+ * functionality in drm_helper_connector_dpms(). -+ * -+ * This callback is also used to disable a CRTC by calling it with -+ * DRM_MODE_DPMS_OFF if the @disable hook isn't used. -+ * -+ * This callback is used by the legacy CRTC helpers. Atomic helpers -+ * also support using this hook for enabling and disabling a CRTC to -+ * facilitate transitions to atomic, but it is deprecated. Instead -+ * @enable and @disable should be used. -+ */ -+ void (*dpms)(struct drm_crtc *crtc, int mode); -+ -+ /** -+ * @prepare: -+ * -+ * This callback should prepare the CRTC for a subsequent modeset, which -+ * in practice means the driver should disable the CRTC if it is -+ * running. Most drivers ended up implementing this by calling their -+ * @dpms hook with DRM_MODE_DPMS_OFF. -+ * -+ * This callback is used by the legacy CRTC helpers. Atomic helpers -+ * also support using this hook for disabling a CRTC to facilitate -+ * transitions to atomic, but it is deprecated. Instead @disable should -+ * be used. -+ */ -+ void (*prepare)(struct drm_crtc *crtc); -+ -+ /** -+ * @commit: -+ * -+ * This callback should commit the new mode on the CRTC after a modeset, -+ * which in practice means the driver should enable the CRTC. Most -+ * drivers ended up implementing this by calling their @dpms hook with -+ * DRM_MODE_DPMS_ON. -+ * -+ * This callback is used by the legacy CRTC helpers. Atomic helpers -+ * also support using this hook for enabling a CRTC to facilitate -+ * transitions to atomic, but it is deprecated. Instead @enable should -+ * be used. -+ */ -+ void (*commit)(struct drm_crtc *crtc); -+ -+ /** -+ * @mode_fixup: -+ * -+ * This callback is used to validate a mode. The parameter mode is the -+ * display mode that userspace requested, adjusted_mode is the mode the -+ * encoders need to be fed with. Note that this is the inverse semantics -+ * of the meaning for the &drm_encoder and &drm_bridge -+ * ->mode_fixup() functions. If the CRTC cannot support the requested -+ * conversion from mode to adjusted_mode it should reject the modeset. -+ * -+ * This function is used by both legacy CRTC helpers and atomic helpers. -+ * This hook is optional. -+ * -+ * NOTE: -+ * -+ * This function is called in the check phase of atomic modesets, which -+ * can be aborted for any reason (including on userspace's request to -+ * just check whether a configuration would be possible). Atomic drivers -+ * MUST NOT touch any persistent state (hardware or software) or data -+ * structures except the passed in adjusted_mode parameter. -+ * -+ * This is in contrast to the legacy CRTC helpers where this was -+ * allowed. -+ * -+ * Atomic drivers which need to inspect and adjust more state should -+ * instead use the @atomic_check callback. -+ * -+ * Also beware that neither core nor helpers filter modes before -+ * passing them to the driver: While the list of modes that is -+ * advertised to userspace is filtered using the connector's -+ * ->mode_valid() callback, neither the core nor the helpers do any -+ * filtering on modes passed in from userspace when setting a mode. It -+ * is therefore possible for userspace to pass in a mode that was -+ * previously filtered out using ->mode_valid() or add a custom mode -+ * that wasn't probed from EDID or similar to begin with. Even though -+ * this is an advanced feature and rarely used nowadays, some users rely -+ * on being able to specify modes manually so drivers must be prepared -+ * to deal with it. Specifically this means that all drivers need not -+ * only validate modes in ->mode_valid() but also in ->mode_fixup() to -+ * make sure invalid modes passed in from userspace are rejected. -+ * -+ * RETURNS: -+ * -+ * True if an acceptable configuration is possible, false if the modeset -+ * operation should be rejected. -+ */ -+ bool (*mode_fixup)(struct drm_crtc *crtc, -+ const struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode); -+ -+ /** -+ * @mode_set: -+ * -+ * This callback is used by the legacy CRTC helpers to set a new mode, -+ * position and framebuffer. Since it ties the primary plane to every -+ * mode change it is incompatible with universal plane support. And -+ * since it can't update other planes it's incompatible with atomic -+ * modeset support. -+ * -+ * This callback is only used by CRTC helpers and deprecated. -+ * -+ * RETURNS: -+ * -+ * 0 on success or a negative error code on failure. -+ */ -+ int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode, int x, int y, -+ struct drm_framebuffer *old_fb); -+ -+ /** -+ * @mode_set_nofb: -+ * -+ * This callback is used to update the display mode of a CRTC without -+ * changing anything of the primary plane configuration. This fits the -+ * requirement of atomic and hence is used by the atomic helpers. It is -+ * also used by the transitional plane helpers to implement a -+ * @mode_set hook in drm_helper_crtc_mode_set(). -+ * -+ * Note that the display pipe is completely off when this function is -+ * called. Atomic drivers which need hardware to be running before they -+ * program the new display mode (e.g. because they implement runtime PM) -+ * should not use this hook. This is because the helper library calls -+ * this hook only once per mode change and not every time the display -+ * pipeline is suspended using either DPMS or the new "ACTIVE" property. -+ * Which means register values set in this callback might get reset when -+ * the CRTC is suspended, but not restored. Such drivers should instead -+ * move all their CRTC setup into the @enable callback. -+ * -+ * This callback is optional. -+ */ -+ void (*mode_set_nofb)(struct drm_crtc *crtc); -+ -+ /** -+ * @mode_set_base: -+ * -+ * This callback is used by the legacy CRTC helpers to set a new -+ * framebuffer and scanout position. It is optional and used as an -+ * optimized fast-path instead of a full mode set operation with all the -+ * resulting flickering. If it is not present -+ * drm_crtc_helper_set_config() will fall back to a full modeset, using -+ * the ->mode_set() callback. Since it can't update other planes it's -+ * incompatible with atomic modeset support. -+ * -+ * This callback is only used by the CRTC helpers and deprecated. -+ * -+ * RETURNS: -+ * -+ * 0 on success or a negative error code on failure. -+ */ -+ int (*mode_set_base)(struct drm_crtc *crtc, int x, int y, -+ struct drm_framebuffer *old_fb); -+ -+ /** -+ * @mode_set_base_atomic: -+ * -+ * This callback is used by the fbdev helpers to set a new framebuffer -+ * and scanout without sleeping, i.e. from an atomic calling context. It -+ * is only used to implement kgdb support. -+ * -+ * This callback is optional and only needed for kgdb support in the fbdev -+ * helpers. -+ * -+ * RETURNS: -+ * -+ * 0 on success or a negative error code on failure. -+ */ -+ int (*mode_set_base_atomic)(struct drm_crtc *crtc, -+ struct drm_framebuffer *fb, int x, int y, -+ enum mode_set_atomic); -+ -+ /** -+ * @load_lut: -+ * -+ * Load a LUT prepared with the @gamma_set functions from -+ * &drm_fb_helper_funcs. -+ * -+ * This callback is optional and is only used by the fbdev emulation -+ * helpers. -+ * -+ * FIXME: -+ * -+ * This callback is functionally redundant with the core gamma table -+ * support and simply exists because the fbdev hasn't yet been -+ * refactored to use the core gamma table interfaces. -+ */ -+ void (*load_lut)(struct drm_crtc *crtc); -+ -+ /** -+ * @disable: -+ * -+ * This callback should be used to disable the CRTC. With the atomic -+ * drivers it is called after all encoders connected to this CRTC have -+ * been shut off already using their own ->disable hook. If that -+ * sequence is too simple drivers can just add their own hooks and call -+ * it from this CRTC callback here by looping over all encoders -+ * connected to it using for_each_encoder_on_crtc(). -+ * -+ * This hook is used both by legacy CRTC helpers and atomic helpers. -+ * Atomic drivers don't need to implement it if there's no need to -+ * disable anything at the CRTC level. To ensure that runtime PM -+ * handling (using either DPMS or the new "ACTIVE" property) works -+ * @disable must be the inverse of @enable for atomic drivers. -+ * -+ * NOTE: -+ * -+ * With legacy CRTC helpers there's a big semantic difference between -+ * @disable and other hooks (like @prepare or @dpms) used to shut down a -+ * CRTC: @disable is only called when also logically disabling the -+ * display pipeline and needs to release any resources acquired in -+ * @mode_set (like shared PLLs, or again release pinned framebuffers). -+ * -+ * Therefore @disable must be the inverse of @mode_set plus @commit for -+ * drivers still using legacy CRTC helpers, which is different from the -+ * rules under atomic. -+ */ -+ void (*disable)(struct drm_crtc *crtc); -+ -+ /** -+ * @enable: -+ * -+ * This callback should be used to enable the CRTC. With the atomic -+ * drivers it is called before all encoders connected to this CRTC are -+ * enabled through the encoder's own ->enable hook. If that sequence is -+ * too simple drivers can just add their own hooks and call it from this -+ * CRTC callback here by looping over all encoders connected to it using -+ * for_each_encoder_on_crtc(). -+ * -+ * This hook is used only by atomic helpers, for symmetry with @disable. -+ * Atomic drivers don't need to implement it if there's no need to -+ * enable anything at the CRTC level. To ensure that runtime PM handling -+ * (using either DPMS or the new "ACTIVE" property) works -+ * @enable must be the inverse of @disable for atomic drivers. -+ */ -+ void (*enable)(struct drm_crtc *crtc); -+ -+ /** -+ * @atomic_check: -+ * -+ * Drivers should check plane-update related CRTC constraints in this -+ * hook. They can also check mode related limitations but need to be -+ * aware of the calling order, since this hook is used by -+ * drm_atomic_helper_check_planes() whereas the preparations needed to -+ * check output routing and the display mode is done in -+ * drm_atomic_helper_check_modeset(). Therefore drivers that want to -+ * check output routing and display mode constraints in this callback -+ * must ensure that drm_atomic_helper_check_modeset() has been called -+ * beforehand. This is calling order used by the default helper -+ * implementation in drm_atomic_helper_check(). -+ * -+ * When using drm_atomic_helper_check_planes() CRTCs' ->atomic_check() -+ * hooks are called after the ones for planes, which allows drivers to -+ * assign shared resources requested by planes in the CRTC callback -+ * here. For more complicated dependencies the driver can call the provided -+ * check helpers multiple times until the computed state has a final -+ * configuration and everything has been checked. -+ * -+ * This function is also allowed to inspect any other object's state and -+ * can add more state objects to the atomic commit if needed. Care must -+ * be taken though to ensure that state check&compute functions for -+ * these added states are all called, and derived state in other objects -+ * all updated. Again the recommendation is to just call check helpers -+ * until a maximal configuration is reached. -+ * -+ * This callback is used by the atomic modeset helpers and by the -+ * transitional plane helpers, but it is optional. -+ * -+ * NOTE: -+ * -+ * This function is called in the check phase of an atomic update. The -+ * driver is not allowed to change anything outside of the free-standing -+ * state objects passed-in or assembled in the overall &drm_atomic_state -+ * update tracking structure. -+ * -+ * RETURNS: -+ * -+ * 0 on success, -EINVAL if the state or the transition can't be -+ * supported, -ENOMEM on memory allocation failure and -EDEADLK if an -+ * attempt to obtain another state object ran into a &drm_modeset_lock -+ * deadlock. -+ */ -+ int (*atomic_check)(struct drm_crtc *crtc, -+ struct drm_crtc_state *state); -+ -+ /** -+ * @atomic_begin: -+ * -+ * Drivers should prepare for an atomic update of multiple planes on -+ * a CRTC in this hook. Depending upon hardware this might be vblank -+ * evasion, blocking updates by setting bits or doing preparatory work -+ * for e.g. manual update display. -+ * -+ * This hook is called before any plane commit functions are called. -+ * -+ * Note that the power state of the display pipe when this function is -+ * called depends upon the exact helpers and calling sequence the driver -+ * has picked. See drm_atomic_commit_planes() for a discussion of the -+ * tradeoffs and variants of plane commit helpers. -+ * -+ * This callback is used by the atomic modeset helpers and by the -+ * transitional plane helpers, but it is optional. -+ */ -+ void (*atomic_begin)(struct drm_crtc *crtc, -+ struct drm_crtc_state *old_crtc_state); -+ /** -+ * @atomic_flush: -+ * -+ * Drivers should finalize an atomic update of multiple planes on -+ * a CRTC in this hook. Depending upon hardware this might include -+ * checking that vblank evasion was successful, unblocking updates by -+ * setting bits or setting the GO bit to flush out all updates. -+ * -+ * Simple hardware or hardware with special requirements can commit and -+ * flush out all updates for all planes from this hook and forgo all the -+ * other commit hooks for plane updates. -+ * -+ * This hook is called after any plane commit functions are called. -+ * -+ * Note that the power state of the display pipe when this function is -+ * called depends upon the exact helpers and calling sequence the driver -+ * has picked. See drm_atomic_commit_planes() for a discussion of the -+ * tradeoffs and variants of plane commit helpers. -+ * -+ * This callback is used by the atomic modeset helpers and by the -+ * transitional plane helpers, but it is optional. -+ */ -+ void (*atomic_flush)(struct drm_crtc *crtc, -+ struct drm_crtc_state *old_crtc_state); -+}; -+ -+/** -+ * drm_crtc_helper_add - sets the helper vtable for a crtc -+ * @crtc: DRM CRTC -+ * @funcs: helper vtable to set for @crtc -+ */ -+static inline void drm_crtc_helper_add(struct drm_crtc *crtc, -+ const struct drm_crtc_helper_funcs *funcs) -+{ -+ crtc->helper_private = funcs; -+} -+ -+/** -+ * struct drm_encoder_helper_funcs - helper operations for encoders -+ * -+ * These hooks are used by the legacy CRTC helpers, the transitional plane -+ * helpers and the new atomic modesetting helpers. -+ */ -+struct drm_encoder_helper_funcs { -+ /** -+ * @dpms: -+ * -+ * Callback to control power levels on the encoder. If the mode passed in -+ * is unsupported, the provider must use the next lowest power level. -+ * This is used by the legacy encoder helpers to implement DPMS -+ * functionality in drm_helper_connector_dpms(). -+ * -+ * This callback is also used to disable an encoder by calling it with -+ * DRM_MODE_DPMS_OFF if the @disable hook isn't used. -+ * -+ * This callback is used by the legacy CRTC helpers. Atomic helpers -+ * also support using this hook for enabling and disabling an encoder to -+ * facilitate transitions to atomic, but it is deprecated. Instead -+ * @enable and @disable should be used. -+ */ -+ void (*dpms)(struct drm_encoder *encoder, int mode); -+ -+ /** -+ * @mode_fixup: -+ * -+ * This callback is used to validate and adjust a mode. The parameter -+ * mode is the display mode that should be fed to the next element in -+ * the display chain, either the final &drm_connector or a &drm_bridge. -+ * The parameter adjusted_mode is the input mode the encoder requires. It -+ * can be modified by this callback and does not need to match mode. -+ * -+ * This function is used by both legacy CRTC helpers and atomic helpers. -+ * This hook is optional. -+ * -+ * NOTE: -+ * -+ * This function is called in the check phase of atomic modesets, which -+ * can be aborted for any reason (including on userspace's request to -+ * just check whether a configuration would be possible). Atomic drivers -+ * MUST NOT touch any persistent state (hardware or software) or data -+ * structures except the passed in adjusted_mode parameter. -+ * -+ * This is in contrast to the legacy CRTC helpers where this was -+ * allowed. -+ * -+ * Atomic drivers which need to inspect and adjust more state should -+ * instead use the @atomic_check callback. -+ * -+ * Also beware that neither core nor helpers filter modes before -+ * passing them to the driver: While the list of modes that is -+ * advertised to userspace is filtered using the connector's -+ * ->mode_valid() callback, neither the core nor the helpers do any -+ * filtering on modes passed in from userspace when setting a mode. It -+ * is therefore possible for userspace to pass in a mode that was -+ * previously filtered out using ->mode_valid() or add a custom mode -+ * that wasn't probed from EDID or similar to begin with. Even though -+ * this is an advanced feature and rarely used nowadays, some users rely -+ * on being able to specify modes manually so drivers must be prepared -+ * to deal with it. Specifically this means that all drivers need not -+ * only validate modes in ->mode_valid() but also in ->mode_fixup() to -+ * make sure invalid modes passed in from userspace are rejected. -+ * -+ * RETURNS: -+ * -+ * True if an acceptable configuration is possible, false if the modeset -+ * operation should be rejected. -+ */ -+ bool (*mode_fixup)(struct drm_encoder *encoder, -+ const struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode); -+ -+ /** -+ * @prepare: -+ * -+ * This callback should prepare the encoder for a subsequent modeset, -+ * which in practice means the driver should disable the encoder if it -+ * is running. Most drivers ended up implementing this by calling their -+ * @dpms hook with DRM_MODE_DPMS_OFF. -+ * -+ * This callback is used by the legacy CRTC helpers. Atomic helpers -+ * also support using this hook for disabling an encoder to facilitate -+ * transitions to atomic, but it is deprecated. Instead @disable should -+ * be used. -+ */ -+ void (*prepare)(struct drm_encoder *encoder); -+ -+ /** -+ * @commit: -+ * -+ * This callback should commit the new mode on the encoder after a modeset, -+ * which in practice means the driver should enable the encoder. Most -+ * drivers ended up implementing this by calling their @dpms hook with -+ * DRM_MODE_DPMS_ON. -+ * -+ * This callback is used by the legacy CRTC helpers. Atomic helpers -+ * also support using this hook for enabling an encoder to facilitate -+ * transitions to atomic, but it is deprecated. Instead @enable should -+ * be used. -+ */ -+ void (*commit)(struct drm_encoder *encoder); -+ -+ /** -+ * @mode_set: -+ * -+ * This callback is used to update the display mode of an encoder. -+ * -+ * Note that the display pipe is completely off when this function is -+ * called. Drivers which need hardware to be running before they program -+ * the new display mode (because they implement runtime PM) should not -+ * use this hook, because the helper library calls it only once and not -+ * every time the display pipeline is suspend using either DPMS or the -+ * new "ACTIVE" property. Such drivers should instead move all their -+ * encoder setup into the ->enable() callback. -+ * -+ * This callback is used both by the legacy CRTC helpers and the atomic -+ * modeset helpers. It is optional in the atomic helpers. -+ */ -+ void (*mode_set)(struct drm_encoder *encoder, -+ struct drm_display_mode *mode, -+ struct drm_display_mode *adjusted_mode); -+ -+ /** -+ * @get_crtc: -+ * -+ * This callback is used by the legacy CRTC helpers to work around -+ * deficiencies in its own book-keeping. -+ * -+ * Do not use, use atomic helpers instead, which get the book keeping -+ * right. -+ * -+ * FIXME: -+ * -+ * Currently only nouveau is using this, and as soon as nouveau is -+ * atomic we can ditch this hook. -+ */ -+ struct drm_crtc *(*get_crtc)(struct drm_encoder *encoder); -+ -+ /** -+ * @detect: -+ * -+ * This callback can be used by drivers who want to do detection on the -+ * encoder object instead of in connector functions. -+ * -+ * It is not used by any helper and therefore has purely driver-specific -+ * semantics. New drivers shouldn't use this and instead just implement -+ * their own private callbacks. -+ * -+ * FIXME: -+ * -+ * This should just be converted into a pile of driver vfuncs. -+ * Currently radeon, amdgpu and nouveau are using it. -+ */ -+ enum drm_connector_status (*detect)(struct drm_encoder *encoder, -+ struct drm_connector *connector); -+ -+ /** -+ * @disable: -+ * -+ * This callback should be used to disable the encoder. With the atomic -+ * drivers it is called before this encoder's CRTC has been shut off -+ * using the CRTC's own ->disable hook. If that sequence is too simple -+ * drivers can just add their own driver private encoder hooks and call -+ * them from CRTC's callback by looping over all encoders connected to -+ * it using for_each_encoder_on_crtc(). -+ * -+ * This hook is used both by legacy CRTC helpers and atomic helpers. -+ * Atomic drivers don't need to implement it if there's no need to -+ * disable anything at the encoder level. To ensure that runtime PM -+ * handling (using either DPMS or the new "ACTIVE" property) works -+ * @disable must be the inverse of @enable for atomic drivers. -+ * -+ * NOTE: -+ * -+ * With legacy CRTC helpers there's a big semantic difference between -+ * @disable and other hooks (like @prepare or @dpms) used to shut down a -+ * encoder: @disable is only called when also logically disabling the -+ * display pipeline and needs to release any resources acquired in -+ * @mode_set (like shared PLLs, or again release pinned framebuffers). -+ * -+ * Therefore @disable must be the inverse of @mode_set plus @commit for -+ * drivers still using legacy CRTC helpers, which is different from the -+ * rules under atomic. -+ */ -+ void (*disable)(struct drm_encoder *encoder); -+ -+ /** -+ * @enable: -+ * -+ * This callback should be used to enable the encoder. With the atomic -+ * drivers it is called after this encoder's CRTC has been enabled using -+ * the CRTC's own ->enable hook. If that sequence is too simple drivers -+ * can just add their own driver private encoder hooks and call them -+ * from CRTC's callback by looping over all encoders connected to it -+ * using for_each_encoder_on_crtc(). -+ * -+ * This hook is used only by atomic helpers, for symmetry with @disable. -+ * Atomic drivers don't need to implement it if there's no need to -+ * enable anything at the encoder level. To ensure that runtime PM handling -+ * (using either DPMS or the new "ACTIVE" property) works -+ * @enable must be the inverse of @disable for atomic drivers. -+ */ -+ void (*enable)(struct drm_encoder *encoder); -+ -+ /** -+ * @atomic_check: -+ * -+ * This callback is used to validate encoder state for atomic drivers. -+ * Since the encoder is the object connecting the CRTC and connector it -+ * gets passed both states, to be able to validate interactions and -+ * update the CRTC to match what the encoder needs for the requested -+ * connector. -+ * -+ * This function is used by the atomic helpers, but it is optional. -+ * -+ * NOTE: -+ * -+ * This function is called in the check phase of an atomic update. The -+ * driver is not allowed to change anything outside of the free-standing -+ * state objects passed-in or assembled in the overall &drm_atomic_state -+ * update tracking structure. -+ * -+ * RETURNS: -+ * -+ * 0 on success, -EINVAL if the state or the transition can't be -+ * supported, -ENOMEM on memory allocation failure and -EDEADLK if an -+ * attempt to obtain another state object ran into a &drm_modeset_lock -+ * deadlock. -+ */ -+ int (*atomic_check)(struct drm_encoder *encoder, -+ struct drm_crtc_state *crtc_state, -+ struct drm_connector_state *conn_state); -+}; -+ -+/** -+ * drm_encoder_helper_add - sets the helper vtable for an encoder -+ * @encoder: DRM encoder -+ * @funcs: helper vtable to set for @encoder -+ */ -+static inline void drm_encoder_helper_add(struct drm_encoder *encoder, -+ const struct drm_encoder_helper_funcs *funcs) -+{ -+ encoder->helper_private = funcs; -+} -+ -+/** -+ * struct drm_connector_helper_funcs - helper operations for connectors -+ * -+ * These functions are used by the atomic and legacy modeset helpers and by the -+ * probe helpers. -+ */ -+struct drm_connector_helper_funcs { -+ /** -+ * @get_modes: -+ * -+ * This function should fill in all modes currently valid for the sink -+ * into the connector->probed_modes list. It should also update the -+ * EDID property by calling drm_mode_connector_update_edid_property(). -+ * -+ * The usual way to implement this is to cache the EDID retrieved in the -+ * probe callback somewhere in the driver-private connector structure. -+ * In this function drivers then parse the modes in the EDID and add -+ * them by calling drm_add_edid_modes(). But connectors that driver a -+ * fixed panel can also manually add specific modes using -+ * drm_mode_probed_add(). Drivers which manually add modes should also -+ * make sure that the @display_info, @width_mm and @height_mm fields of the -+ * struct #drm_connector are filled in. -+ * -+ * Virtual drivers that just want some standard VESA mode with a given -+ * resolution can call drm_add_modes_noedid(), and mark the preferred -+ * one using drm_set_preferred_mode(). -+ * -+ * Finally drivers that support audio probably want to update the ELD -+ * data, too, using drm_edid_to_eld(). -+ * -+ * This function is only called after the ->detect() hook has indicated -+ * that a sink is connected and when the EDID isn't overridden through -+ * sysfs or the kernel commandline. -+ * -+ * This callback is used by the probe helpers in e.g. -+ * drm_helper_probe_single_connector_modes(). -+ * -+ * RETURNS: -+ * -+ * The number of modes added by calling drm_mode_probed_add(). -+ */ -+ int (*get_modes)(struct drm_connector *connector); -+ -+ /** -+ * @mode_valid: -+ * -+ * Callback to validate a mode for a connector, irrespective of the -+ * specific display configuration. -+ * -+ * This callback is used by the probe helpers to filter the mode list -+ * (which is usually derived from the EDID data block from the sink). -+ * See e.g. drm_helper_probe_single_connector_modes(). -+ * -+ * NOTE: -+ * -+ * This only filters the mode list supplied to userspace in the -+ * GETCONNECOTR IOCTL. Userspace is free to create modes of its own and -+ * ask the kernel to use them. It this case the atomic helpers or legacy -+ * CRTC helpers will not call this function. Drivers therefore must -+ * still fully validate any mode passed in in a modeset request. -+ * -+ * RETURNS: -+ * -+ * Either MODE_OK or one of the failure reasons in enum -+ * &drm_mode_status. -+ */ -+ enum drm_mode_status (*mode_valid)(struct drm_connector *connector, -+ struct drm_display_mode *mode); -+ /** -+ * @best_encoder: -+ * -+ * This function should select the best encoder for the given connector. -+ * -+ * This function is used by both the atomic helpers (in the -+ * drm_atomic_helper_check_modeset() function) and in the legacy CRTC -+ * helpers. -+ * -+ * NOTE: -+ * -+ * In atomic drivers this function is called in the check phase of an -+ * atomic update. The driver is not allowed to change or inspect -+ * anything outside of arguments passed-in. Atomic drivers which need to -+ * inspect dynamic configuration state should instead use -+ * @atomic_best_encoder. -+ * -+ * RETURNS: -+ * -+ * Encoder that should be used for the given connector and connector -+ * state, or NULL if no suitable encoder exists. Note that the helpers -+ * will ensure that encoders aren't used twice, drivers should not check -+ * for this. -+ */ -+ struct drm_encoder *(*best_encoder)(struct drm_connector *connector); -+ -+ /** -+ * @atomic_best_encoder: -+ * -+ * This is the atomic version of @best_encoder for atomic drivers which -+ * need to select the best encoder depending upon the desired -+ * configuration and can't select it statically. -+ * -+ * This function is used by drm_atomic_helper_check_modeset() and either -+ * this or @best_encoder is required. -+ * -+ * NOTE: -+ * -+ * This function is called in the check phase of an atomic update. The -+ * driver is not allowed to change anything outside of the free-standing -+ * state objects passed-in or assembled in the overall &drm_atomic_state -+ * update tracking structure. -+ * -+ * RETURNS: -+ * -+ * Encoder that should be used for the given connector and connector -+ * state, or NULL if no suitable encoder exists. Note that the helpers -+ * will ensure that encoders aren't used twice, drivers should not check -+ * for this. -+ */ -+ struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, -+ struct drm_connector_state *connector_state); -+}; -+ -+/** -+ * drm_connector_helper_add - sets the helper vtable for a connector -+ * @connector: DRM connector -+ * @funcs: helper vtable to set for @connector -+ */ -+static inline void drm_connector_helper_add(struct drm_connector *connector, -+ const struct drm_connector_helper_funcs *funcs) -+{ -+ connector->helper_private = funcs; -+} -+ -+/** -+ * struct drm_plane_helper_funcs - helper operations for planes -+ * -+ * These functions are used by the atomic helpers and by the transitional plane -+ * helpers. -+ */ -+struct drm_plane_helper_funcs { -+ /** -+ * @prepare_fb: -+ * -+ * This hook is to prepare a framebuffer for scanout by e.g. pinning -+ * it's backing storage or relocating it into a contiguous block of -+ * VRAM. Other possible preparatory work includes flushing caches. -+ * -+ * This function must not block for outstanding rendering, since it is -+ * called in the context of the atomic IOCTL even for async commits to -+ * be able to return any errors to userspace. Instead the recommended -+ * way is to fill out the fence member of the passed-in -+ * &drm_plane_state. If the driver doesn't support native fences then -+ * equivalent functionality should be implemented through private -+ * members in the plane structure. -+ * -+ * The helpers will call @cleanup_fb with matching arguments for every -+ * successful call to this hook. -+ * -+ * This callback is used by the atomic modeset helpers and by the -+ * transitional plane helpers, but it is optional. -+ * -+ * RETURNS: -+ * -+ * 0 on success or one of the following negative error codes allowed by -+ * the atomic_commit hook in &drm_mode_config_funcs. When using helpers -+ * this callback is the only one which can fail an atomic commit, -+ * everything else must complete successfully. -+ */ -+ int (*prepare_fb)(struct drm_plane *plane, -+ const struct drm_plane_state *new_state); -+ /** -+ * @cleanup_fb: -+ * -+ * This hook is called to clean up any resources allocated for the given -+ * framebuffer and plane configuration in @prepare_fb. -+ * -+ * This callback is used by the atomic modeset helpers and by the -+ * transitional plane helpers, but it is optional. -+ */ -+ void (*cleanup_fb)(struct drm_plane *plane, -+ const struct drm_plane_state *old_state); -+ -+ /** -+ * @atomic_check: -+ * -+ * Drivers should check plane specific constraints in this hook. -+ * -+ * When using drm_atomic_helper_check_planes() plane's ->atomic_check() -+ * hooks are called before the ones for CRTCs, which allows drivers to -+ * request shared resources that the CRTC controls here. For more -+ * complicated dependencies the driver can call the provided check helpers -+ * multiple times until the computed state has a final configuration and -+ * everything has been checked. -+ * -+ * This function is also allowed to inspect any other object's state and -+ * can add more state objects to the atomic commit if needed. Care must -+ * be taken though to ensure that state check&compute functions for -+ * these added states are all called, and derived state in other objects -+ * all updated. Again the recommendation is to just call check helpers -+ * until a maximal configuration is reached. -+ * -+ * This callback is used by the atomic modeset helpers and by the -+ * transitional plane helpers, but it is optional. -+ * -+ * NOTE: -+ * -+ * This function is called in the check phase of an atomic update. The -+ * driver is not allowed to change anything outside of the free-standing -+ * state objects passed-in or assembled in the overall &drm_atomic_state -+ * update tracking structure. -+ * -+ * RETURNS: -+ * -+ * 0 on success, -EINVAL if the state or the transition can't be -+ * supported, -ENOMEM on memory allocation failure and -EDEADLK if an -+ * attempt to obtain another state object ran into a &drm_modeset_lock -+ * deadlock. -+ */ -+ int (*atomic_check)(struct drm_plane *plane, -+ struct drm_plane_state *state); -+ -+ /** -+ * @atomic_update: -+ * -+ * Drivers should use this function to update the plane state. This -+ * hook is called in-between the ->atomic_begin() and -+ * ->atomic_flush() of &drm_crtc_helper_funcs. -+ * -+ * Note that the power state of the display pipe when this function is -+ * called depends upon the exact helpers and calling sequence the driver -+ * has picked. See drm_atomic_commit_planes() for a discussion of the -+ * tradeoffs and variants of plane commit helpers. -+ * -+ * This callback is used by the atomic modeset helpers and by the -+ * transitional plane helpers, but it is optional. -+ */ -+ void (*atomic_update)(struct drm_plane *plane, -+ struct drm_plane_state *old_state); -+ /** -+ * @atomic_disable: -+ * -+ * Drivers should use this function to unconditionally disable a plane. -+ * This hook is called in-between the ->atomic_begin() and -+ * ->atomic_flush() of &drm_crtc_helper_funcs. It is an alternative to -+ * @atomic_update, which will be called for disabling planes, too, if -+ * the @atomic_disable hook isn't implemented. -+ * -+ * This hook is also useful to disable planes in preparation of a modeset, -+ * by calling drm_atomic_helper_disable_planes_on_crtc() from the -+ * ->disable() hook in &drm_crtc_helper_funcs. -+ * -+ * Note that the power state of the display pipe when this function is -+ * called depends upon the exact helpers and calling sequence the driver -+ * has picked. See drm_atomic_commit_planes() for a discussion of the -+ * tradeoffs and variants of plane commit helpers. -+ * -+ * This callback is used by the atomic modeset helpers and by the -+ * transitional plane helpers, but it is optional. -+ */ -+ void (*atomic_disable)(struct drm_plane *plane, -+ struct drm_plane_state *old_state); -+}; -+ -+/** -+ * drm_plane_helper_add - sets the helper vtable for a plane -+ * @plane: DRM plane -+ * @funcs: helper vtable to set for @plane -+ */ -+static inline void drm_plane_helper_add(struct drm_plane *plane, -+ const struct drm_plane_helper_funcs *funcs) -+{ -+ plane->helper_private = funcs; -+} -+ -+#endif --- -2.5.5 - diff --git a/linux/0003-drm-fixes-crct-set_mode-when-crtc-mode_fixup-is-null.patch b/linux/0003-drm-fixes-crct-set_mode-when-crtc-mode_fixup-is-null.patch deleted file mode 100644 index e3689d249d4..00000000000 --- a/linux/0003-drm-fixes-crct-set_mode-when-crtc-mode_fixup-is-null.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 5343f4ffefee5a38c1f5aad7afd6cb6c9c269d31 Mon Sep 17 00:00:00 2001 -From: Carlos Palminha -Date: Tue, 16 Feb 2016 14:10:03 +0000 -Subject: [PATCH 3/9] drm: fixes crct set_mode when crtc mode_fixup is null. - -This patch set nukes all the dummy crtc mode_fixup implementations. -(made on top of Daniel topic/drm-misc branch) - -Signed-off-by: Carlos Palminha -Signed-off-by: Daniel Vetter -Link: http://patchwork.freedesktop.org/patch/msgid/9d41105dee6632b4bb50e9555f2196ac249b9fce.1455630967.git.palminha@synopsys.com ---- - drivers/gpu/drm/drm_crtc_helper.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c -index 5becaa2..9f0347c 100644 ---- a/drivers/gpu/drm/drm_crtc_helper.c -+++ b/drivers/gpu/drm/drm_crtc_helper.c -@@ -327,9 +327,12 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, - } - } - -- if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { -- DRM_DEBUG_KMS("CRTC fixup failed\n"); -- goto done; -+ if (crtc_funcs->mode_fixup) { -+ if (!(ret = crtc_funcs->mode_fixup(crtc, mode, -+ adjusted_mode))) { -+ DRM_DEBUG_KMS("CRTC fixup failed\n"); -+ goto done; -+ } - } - DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); - --- -2.5.5 - diff --git a/linux/0004-arc-convert-to-dma_map_ops.patch b/linux/0004-arc-convert-to-dma_map_ops.patch deleted file mode 100644 index a5115af9688..00000000000 --- a/linux/0004-arc-convert-to-dma_map_ops.patch +++ /dev/null @@ -1,438 +0,0 @@ -From d41d0e3ea8f48627c789fc69f2d340671ae22b0d Mon Sep 17 00:00:00 2001 -From: Christoph Hellwig -Date: Wed, 20 Jan 2016 15:01:26 -0800 -Subject: [PATCH 4/9] arc: convert to dma_map_ops - -[vgupta@synopsys.com: ARC: dma mapping fixes #2] -Signed-off-by: Christoph Hellwig -Cc: Vineet Gupta -Cc: Christian Borntraeger -Cc: Joerg Roedel -Cc: Sebastian Ott -Signed-off-by: Vineet Gupta -Cc: Carlos Palminha -Signed-off-by: Andrew Morton -Signed-off-by: Linus Torvalds ---- - arch/arc/Kconfig | 1 + - arch/arc/include/asm/dma-mapping.h | 187 +------------------------------------ - arch/arc/mm/dma.c | 152 ++++++++++++++++++++---------- - 3 files changed, 110 insertions(+), 230 deletions(-) - -diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig -index 6312f60..c22f5d4 100644 ---- a/arch/arc/Kconfig -+++ b/arch/arc/Kconfig -@@ -38,6 +38,7 @@ config ARC - select OF_EARLY_FLATTREE - select PERF_USE_VMALLOC - select HAVE_DEBUG_STACKOVERFLOW -+ select HAVE_DMA_ATTRS - - config TRACE_IRQFLAGS_SUPPORT - def_bool y -diff --git a/arch/arc/include/asm/dma-mapping.h b/arch/arc/include/asm/dma-mapping.h -index 2d28ba9..2a617f9 100644 ---- a/arch/arc/include/asm/dma-mapping.h -+++ b/arch/arc/include/asm/dma-mapping.h -@@ -11,192 +11,13 @@ - #ifndef ASM_ARC_DMA_MAPPING_H - #define ASM_ARC_DMA_MAPPING_H - --#include --#include -+extern struct dma_map_ops arc_dma_ops; - --void *dma_alloc_noncoherent(struct device *dev, size_t size, -- dma_addr_t *dma_handle, gfp_t gfp); -- --void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle); -- --void *dma_alloc_coherent(struct device *dev, size_t size, -- dma_addr_t *dma_handle, gfp_t gfp); -- --void dma_free_coherent(struct device *dev, size_t size, void *kvaddr, -- dma_addr_t dma_handle); -- --/* drivers/base/dma-mapping.c */ --extern int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, -- void *cpu_addr, dma_addr_t dma_addr, size_t size); --extern int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, -- void *cpu_addr, dma_addr_t dma_addr, -- size_t size); -- --#define dma_mmap_coherent(d, v, c, h, s) dma_common_mmap(d, v, c, h, s) --#define dma_get_sgtable(d, t, v, h, s) dma_common_get_sgtable(d, t, v, h, s) -- --/* -- * streaming DMA Mapping API... -- * CPU accesses page via normal paddr, thus needs to explicitly made -- * consistent before each use -- */ -- --static inline void __inline_dma_cache_sync(unsigned long paddr, size_t size, -- enum dma_data_direction dir) --{ -- switch (dir) { -- case DMA_FROM_DEVICE: -- dma_cache_inv(paddr, size); -- break; -- case DMA_TO_DEVICE: -- dma_cache_wback(paddr, size); -- break; -- case DMA_BIDIRECTIONAL: -- dma_cache_wback_inv(paddr, size); -- break; -- default: -- pr_err("Invalid DMA dir [%d] for OP @ %lx\n", dir, paddr); -- } --} -- --void __arc_dma_cache_sync(unsigned long paddr, size_t size, -- enum dma_data_direction dir); -- --#define _dma_cache_sync(addr, sz, dir) \ --do { \ -- if (__builtin_constant_p(dir)) \ -- __inline_dma_cache_sync(addr, sz, dir); \ -- else \ -- __arc_dma_cache_sync(addr, sz, dir); \ --} \ --while (0); -- --static inline dma_addr_t --dma_map_single(struct device *dev, void *cpu_addr, size_t size, -- enum dma_data_direction dir) --{ -- _dma_cache_sync((unsigned long)cpu_addr, size, dir); -- return (dma_addr_t)cpu_addr; --} -- --static inline void --dma_unmap_single(struct device *dev, dma_addr_t dma_addr, -- size_t size, enum dma_data_direction dir) --{ --} -- --static inline dma_addr_t --dma_map_page(struct device *dev, struct page *page, -- unsigned long offset, size_t size, -- enum dma_data_direction dir) --{ -- unsigned long paddr = page_to_phys(page) + offset; -- return dma_map_single(dev, (void *)paddr, size, dir); --} -- --static inline void --dma_unmap_page(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction dir) --{ --} -- --static inline int --dma_map_sg(struct device *dev, struct scatterlist *sg, -- int nents, enum dma_data_direction dir) --{ -- struct scatterlist *s; -- int i; -- -- for_each_sg(sg, s, nents, i) -- s->dma_address = dma_map_page(dev, sg_page(s), s->offset, -- s->length, dir); -- -- return nents; --} -- --static inline void --dma_unmap_sg(struct device *dev, struct scatterlist *sg, -- int nents, enum dma_data_direction dir) -+static inline struct dma_map_ops *get_dma_ops(struct device *dev) - { -- struct scatterlist *s; -- int i; -- -- for_each_sg(sg, s, nents, i) -- dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir); --} -- --static inline void --dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction dir) --{ -- _dma_cache_sync(dma_handle, size, DMA_FROM_DEVICE); --} -- --static inline void --dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, -- size_t size, enum dma_data_direction dir) --{ -- _dma_cache_sync(dma_handle, size, DMA_TO_DEVICE); --} -- --static inline void --dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, -- enum dma_data_direction direction) --{ -- _dma_cache_sync(dma_handle + offset, size, DMA_FROM_DEVICE); --} -- --static inline void --dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, -- unsigned long offset, size_t size, -- enum dma_data_direction direction) --{ -- _dma_cache_sync(dma_handle + offset, size, DMA_TO_DEVICE); -+ return &arc_dma_ops; - } - --static inline void --dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, int nelems, -- enum dma_data_direction dir) --{ -- int i; -- struct scatterlist *sg; -- -- for_each_sg(sglist, sg, nelems, i) -- _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir); --} -- --static inline void --dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist, -- int nelems, enum dma_data_direction dir) --{ -- int i; -- struct scatterlist *sg; -- -- for_each_sg(sglist, sg, nelems, i) -- _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir); --} -- --static inline int dma_supported(struct device *dev, u64 dma_mask) --{ -- /* Support 32 bit DMA mask exclusively */ -- return dma_mask == DMA_BIT_MASK(32); --} -- --static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) --{ -- return 0; --} -- --static inline int dma_set_mask(struct device *dev, u64 dma_mask) --{ -- if (!dev->dma_mask || !dma_supported(dev, dma_mask)) -- return -EIO; -- -- *dev->dma_mask = dma_mask; -- -- return 0; --} -+#include - - #endif -diff --git a/arch/arc/mm/dma.c b/arch/arc/mm/dma.c -index 29a46bb..01eaf88 100644 ---- a/arch/arc/mm/dma.c -+++ b/arch/arc/mm/dma.c -@@ -17,18 +17,14 @@ - */ - - #include --#include --#include - #include - #include - --/* -- * Helpers for Coherent DMA API. -- */ --void *dma_alloc_noncoherent(struct device *dev, size_t size, -- dma_addr_t *dma_handle, gfp_t gfp) -+ -+static void *arc_dma_alloc(struct device *dev, size_t size, -+ dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs) - { -- void *paddr; -+ void *paddr, *kvaddr; - - /* This is linear addr (0x8000_0000 based) */ - paddr = alloc_pages_exact(size, gfp); -@@ -38,22 +34,6 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size, - /* This is bus address, platform dependent */ - *dma_handle = (dma_addr_t)paddr; - -- return paddr; --} --EXPORT_SYMBOL(dma_alloc_noncoherent); -- --void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, -- dma_addr_t dma_handle) --{ -- free_pages_exact((void *)dma_handle, size); --} --EXPORT_SYMBOL(dma_free_noncoherent); -- --void *dma_alloc_coherent(struct device *dev, size_t size, -- dma_addr_t *dma_handle, gfp_t gfp) --{ -- void *paddr, *kvaddr; -- - /* - * IOC relies on all data (even coherent DMA data) being in cache - * Thus allocate normal cached memory -@@ -65,22 +45,15 @@ void *dma_alloc_coherent(struct device *dev, size_t size, - * -For coherent data, Read/Write to buffers terminate early in cache - * (vs. always going to memory - thus are faster) - */ -- if (is_isa_arcv2() && ioc_exists) -- return dma_alloc_noncoherent(dev, size, dma_handle, gfp); -- -- /* This is linear addr (0x8000_0000 based) */ -- paddr = alloc_pages_exact(size, gfp); -- if (!paddr) -- return NULL; -+ if ((is_isa_arcv2() && ioc_exists) || -+ dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs)) -+ return paddr; - - /* This is kernel Virtual address (0x7000_0000 based) */ - kvaddr = ioremap_nocache((unsigned long)paddr, size); - if (kvaddr == NULL) - return NULL; - -- /* This is bus address, platform dependent */ -- *dma_handle = (dma_addr_t)paddr; -- - /* - * Evict any existing L1 and/or L2 lines for the backing page - * in case it was used earlier as a normal "cached" page. -@@ -95,26 +68,111 @@ void *dma_alloc_coherent(struct device *dev, size_t size, - - return kvaddr; - } --EXPORT_SYMBOL(dma_alloc_coherent); - --void dma_free_coherent(struct device *dev, size_t size, void *kvaddr, -- dma_addr_t dma_handle) -+static void arc_dma_free(struct device *dev, size_t size, void *vaddr, -+ dma_addr_t dma_handle, struct dma_attrs *attrs) - { -- if (is_isa_arcv2() && ioc_exists) -- return dma_free_noncoherent(dev, size, kvaddr, dma_handle); -- -- iounmap((void __force __iomem *)kvaddr); -+ if (!dma_get_attr(DMA_ATTR_NON_CONSISTENT, attrs) && -+ !(is_isa_arcv2() && ioc_exists)) -+ iounmap((void __force __iomem *)vaddr); - - free_pages_exact((void *)dma_handle, size); - } --EXPORT_SYMBOL(dma_free_coherent); - - /* -- * Helper for streaming DMA... -+ * streaming DMA Mapping API... -+ * CPU accesses page via normal paddr, thus needs to explicitly made -+ * consistent before each use - */ --void __arc_dma_cache_sync(unsigned long paddr, size_t size, -- enum dma_data_direction dir) -+static void _dma_cache_sync(unsigned long paddr, size_t size, -+ enum dma_data_direction dir) -+{ -+ switch (dir) { -+ case DMA_FROM_DEVICE: -+ dma_cache_inv(paddr, size); -+ break; -+ case DMA_TO_DEVICE: -+ dma_cache_wback(paddr, size); -+ break; -+ case DMA_BIDIRECTIONAL: -+ dma_cache_wback_inv(paddr, size); -+ break; -+ default: -+ pr_err("Invalid DMA dir [%d] for OP @ %lx\n", dir, paddr); -+ } -+} -+ -+static dma_addr_t arc_dma_map_page(struct device *dev, struct page *page, -+ unsigned long offset, size_t size, enum dma_data_direction dir, -+ struct dma_attrs *attrs) -+{ -+ unsigned long paddr = page_to_phys(page) + offset; -+ _dma_cache_sync(paddr, size, dir); -+ return (dma_addr_t)paddr; -+} -+ -+static int arc_dma_map_sg(struct device *dev, struct scatterlist *sg, -+ int nents, enum dma_data_direction dir, struct dma_attrs *attrs) -+{ -+ struct scatterlist *s; -+ int i; -+ -+ for_each_sg(sg, s, nents, i) -+ s->dma_address = dma_map_page(dev, sg_page(s), s->offset, -+ s->length, dir); -+ -+ return nents; -+} -+ -+static void arc_dma_sync_single_for_cpu(struct device *dev, -+ dma_addr_t dma_handle, size_t size, enum dma_data_direction dir) -+{ -+ _dma_cache_sync(dma_handle, size, DMA_FROM_DEVICE); -+} -+ -+static void arc_dma_sync_single_for_device(struct device *dev, -+ dma_addr_t dma_handle, size_t size, enum dma_data_direction dir) - { -- __inline_dma_cache_sync(paddr, size, dir); -+ _dma_cache_sync(dma_handle, size, DMA_TO_DEVICE); - } --EXPORT_SYMBOL(__arc_dma_cache_sync); -+ -+static void arc_dma_sync_sg_for_cpu(struct device *dev, -+ struct scatterlist *sglist, int nelems, -+ enum dma_data_direction dir) -+{ -+ int i; -+ struct scatterlist *sg; -+ -+ for_each_sg(sglist, sg, nelems, i) -+ _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir); -+} -+ -+static void arc_dma_sync_sg_for_device(struct device *dev, -+ struct scatterlist *sglist, int nelems, -+ enum dma_data_direction dir) -+{ -+ int i; -+ struct scatterlist *sg; -+ -+ for_each_sg(sglist, sg, nelems, i) -+ _dma_cache_sync((unsigned int)sg_virt(sg), sg->length, dir); -+} -+ -+static int arc_dma_supported(struct device *dev, u64 dma_mask) -+{ -+ /* Support 32 bit DMA mask exclusively */ -+ return dma_mask == DMA_BIT_MASK(32); -+} -+ -+struct dma_map_ops arc_dma_ops = { -+ .alloc = arc_dma_alloc, -+ .free = arc_dma_free, -+ .map_page = arc_dma_map_page, -+ .map_sg = arc_dma_map_sg, -+ .sync_single_for_device = arc_dma_sync_single_for_device, -+ .sync_single_for_cpu = arc_dma_sync_single_for_cpu, -+ .sync_sg_for_cpu = arc_dma_sync_sg_for_cpu, -+ .sync_sg_for_device = arc_dma_sync_sg_for_device, -+ .dma_supported = arc_dma_supported, -+}; -+EXPORT_SYMBOL(arc_dma_ops); --- -2.5.5 - diff --git a/linux/0005-arc-Add-our-own-implementation-of-fb_pgprotect.patch b/linux/0005-arc-Add-our-own-implementation-of-fb_pgprotect.patch deleted file mode 100644 index 3297f0de3a2..00000000000 --- a/linux/0005-arc-Add-our-own-implementation-of-fb_pgprotect.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 7bdc8e1fac981baa7b89d22c3af129adc2f14703 Mon Sep 17 00:00:00 2001 -From: Alexey Brodkin -Date: Mon, 28 Mar 2016 14:36:38 +0300 -Subject: [PATCH 5/9] arc: Add our own implementation of fb_pgprotect() - -During mmaping of frame-buffer pages to user-space -fb_protect() is called to set proper page settings. - -In case of ARC we need to mark pages that are mmaped to -user as uncached because of 2 reasons: - * Huge amount of data if passing through data cache will - thrash cache a lot making cache almost useless for other - less traffic hungry processes. - * Data written by user in FB will be immediately available for - hardware (such as PGU etc) without requirements to flush data - cache regularly. - -Signed-off-by: Alexey Brodkin -Cc: Vineet Gupta -Cc: linux-snps-arc@lists.infradead.org ---- - arch/arc/include/asm/fb.h | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - create mode 100644 arch/arc/include/asm/fb.h - -diff --git a/arch/arc/include/asm/fb.h b/arch/arc/include/asm/fb.h -new file mode 100644 -index 0000000..bd3f68c ---- /dev/null -+++ b/arch/arc/include/asm/fb.h -@@ -0,0 +1,19 @@ -+#ifndef _ASM_FB_H_ -+#define _ASM_FB_H_ -+ -+#include -+#include -+#include -+ -+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, -+ unsigned long off) -+{ -+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); -+} -+ -+static inline int fb_is_primary_device(struct fb_info *info) -+{ -+ return 0; -+} -+ -+#endif /* _ASM_FB_H_ */ --- -2.5.5 - diff --git a/linux/0006-drm-Add-support-of-ARC-PGU-display-controller.patch b/linux/0006-drm-Add-support-of-ARC-PGU-display-controller.patch deleted file mode 100644 index aee4350571f..00000000000 --- a/linux/0006-drm-Add-support-of-ARC-PGU-display-controller.patch +++ /dev/null @@ -1,944 +0,0 @@ -From 8545014932ba247242db97ff4c9a469739ce0275 Mon Sep 17 00:00:00 2001 -From: Alexey Brodkin -Date: Fri, 1 Apr 2016 15:38:39 +0300 -Subject: [PATCH 6/9] drm: Add support of ARC PGU display controller - -ARC PGU could be found on some development boards from Synopsys. -This is a simple byte streamer that reads data from a framebuffer -and sends data to the single encoder. - -This patch is made of v5 upstream submission could be found here: -https://lists.freedesktop.org/archives/dri-devel/2016-March/103720.html - -It was hand modified to apply cleanly on v4.4. - -Signed-off-by: Carlos Palminha -Signed-off-by: Alexey Brodkin -Cc: David Airlie -Cc: dri-devel@lists.freedesktop.org -Cc: linux-snps-arc@lists.infradead.org ---- - drivers/gpu/drm/Kconfig | 2 + - drivers/gpu/drm/Makefile | 1 + - drivers/gpu/drm/arc/Kconfig | 10 ++ - drivers/gpu/drm/arc/Makefile | 2 + - drivers/gpu/drm/arc/arcpgu.h | 50 +++++++ - drivers/gpu/drm/arc/arcpgu_crtc.c | 257 ++++++++++++++++++++++++++++++++++ - drivers/gpu/drm/arc/arcpgu_drv.c | 282 ++++++++++++++++++++++++++++++++++++++ - drivers/gpu/drm/arc/arcpgu_hdmi.c | 201 +++++++++++++++++++++++++++ - drivers/gpu/drm/arc/arcpgu_regs.h | 40 ++++++ - 9 files changed, 845 insertions(+) - create mode 100644 drivers/gpu/drm/arc/Kconfig - create mode 100644 drivers/gpu/drm/arc/Makefile - create mode 100644 drivers/gpu/drm/arc/arcpgu.h - create mode 100644 drivers/gpu/drm/arc/arcpgu_crtc.c - create mode 100644 drivers/gpu/drm/arc/arcpgu_drv.c - create mode 100644 drivers/gpu/drm/arc/arcpgu_hdmi.c - create mode 100644 drivers/gpu/drm/arc/arcpgu_regs.h - -diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig -index c4bf9a1..0df98a2 100644 ---- a/drivers/gpu/drm/Kconfig -+++ b/drivers/gpu/drm/Kconfig -@@ -266,3 +266,5 @@ source "drivers/gpu/drm/amd/amdkfd/Kconfig" - source "drivers/gpu/drm/imx/Kconfig" - - source "drivers/gpu/drm/vc4/Kconfig" -+ -+source "drivers/gpu/drm/arc/Kconfig" -diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile -index 1e9ff4c..2007c1b 100644 ---- a/drivers/gpu/drm/Makefile -+++ b/drivers/gpu/drm/Makefile -@@ -75,3 +75,4 @@ obj-y += i2c/ - obj-y += panel/ - obj-y += bridge/ - obj-$(CONFIG_DRM_FSL_DCU) += fsl-dcu/ -+obj-$(CONFIG_DRM_ARCPGU)+= arc/ -diff --git a/drivers/gpu/drm/arc/Kconfig b/drivers/gpu/drm/arc/Kconfig -new file mode 100644 -index 0000000..f9a13b6 ---- /dev/null -+++ b/drivers/gpu/drm/arc/Kconfig -@@ -0,0 +1,10 @@ -+config DRM_ARCPGU -+ tristate "ARC PGU" -+ depends on DRM && OF -+ select DRM_KMS_CMA_HELPER -+ select DRM_KMS_FB_HELPER -+ select DRM_KMS_HELPER -+ help -+ Choose this option if you have an ARC PGU controller. -+ -+ If M is selected the module will be called arcpgu. -diff --git a/drivers/gpu/drm/arc/Makefile b/drivers/gpu/drm/arc/Makefile -new file mode 100644 -index 0000000..d48fda7 ---- /dev/null -+++ b/drivers/gpu/drm/arc/Makefile -@@ -0,0 +1,2 @@ -+arcpgu-y := arcpgu_crtc.o arcpgu_hdmi.o arcpgu_drv.o -+obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o -diff --git a/drivers/gpu/drm/arc/arcpgu.h b/drivers/gpu/drm/arc/arcpgu.h -new file mode 100644 -index 0000000..86574b6 ---- /dev/null -+++ b/drivers/gpu/drm/arc/arcpgu.h -@@ -0,0 +1,50 @@ -+/* -+ * ARC PGU DRM driver. -+ * -+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#ifndef _ARCPGU_H_ -+#define _ARCPGU_H_ -+ -+struct arcpgu_drm_private { -+ void __iomem *regs; -+ struct clk *clk; -+ struct drm_fbdev_cma *fbdev; -+ struct drm_framebuffer *fb; -+ struct list_head event_list; -+ struct drm_crtc crtc; -+ struct drm_plane *plane; -+}; -+ -+#define crtc_to_arcpgu_priv(x) container_of(x, struct arcpgu_drm_private, crtc) -+ -+static inline void arc_pgu_write(struct arcpgu_drm_private *arcpgu, -+ unsigned int reg, u32 value) -+{ -+ iowrite32(value, arcpgu->regs + reg); -+} -+ -+static inline u32 arc_pgu_read(struct arcpgu_drm_private *arcpgu, -+ unsigned int reg) -+{ -+ return ioread32(arcpgu->regs + reg); -+} -+ -+int arc_pgu_setup_crtc(struct drm_device *dev); -+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np); -+struct drm_fbdev_cma *arcpgu_fbdev_cma_init(struct drm_device *dev, -+ unsigned int preferred_bpp, unsigned int num_crtc, -+ unsigned int max_conn_count); -+ -+#endif -diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c -new file mode 100644 -index 0000000..92f8bef ---- /dev/null -+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c -@@ -0,0 +1,257 @@ -+/* -+ * ARC PGU DRM driver. -+ * -+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "arcpgu.h" -+#include "arcpgu_regs.h" -+ -+#define ENCODE_PGU_XY(x, y) ((((x) - 1) << 16) | ((y) - 1)) -+ -+static struct simplefb_format supported_formats[] = { -+ { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 }, -+ { "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 }, -+}; -+ -+static void arc_pgu_set_pxl_fmt(struct drm_crtc *crtc) -+{ -+ struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); -+ uint32_t pixel_format = crtc->primary->state->fb->pixel_format; -+ struct simplefb_format *format = NULL; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(supported_formats); i++) { -+ if (supported_formats[i].fourcc == pixel_format) -+ format = &supported_formats[i]; -+ } -+ -+ if (WARN_ON(!format)) -+ return; -+ -+ if (format->fourcc == DRM_FORMAT_RGB888) -+ arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, -+ arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) | -+ ARCPGU_MODE_RGB888_MASK); -+ -+} -+ -+static const struct drm_crtc_funcs arc_pgu_crtc_funcs = { -+ .destroy = drm_crtc_cleanup, -+ .set_config = drm_atomic_helper_set_config, -+ .page_flip = drm_atomic_helper_page_flip, -+ .reset = drm_atomic_helper_crtc_reset, -+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, -+}; -+ -+static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc) -+{ -+ struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); -+ struct drm_display_mode *m = &crtc->state->adjusted_mode; -+ u32 val; -+ -+ arc_pgu_write(arcpgu, ARCPGU_REG_FMT, -+ ENCODE_PGU_XY(m->crtc_htotal, m->crtc_vtotal)); -+ -+ arc_pgu_write(arcpgu, ARCPGU_REG_HSYNC, -+ ENCODE_PGU_XY(m->crtc_hsync_start - m->crtc_hdisplay, -+ m->crtc_hsync_end - m->crtc_hdisplay)); -+ -+ arc_pgu_write(arcpgu, ARCPGU_REG_VSYNC, -+ ENCODE_PGU_XY(m->crtc_vsync_start - m->crtc_vdisplay, -+ m->crtc_vsync_end - m->crtc_vdisplay)); -+ -+ arc_pgu_write(arcpgu, ARCPGU_REG_ACTIVE, -+ ENCODE_PGU_XY(m->crtc_hblank_end - m->crtc_hblank_start, -+ m->crtc_vblank_end - m->crtc_vblank_start)); -+ -+ val = arc_pgu_read(arcpgu, ARCPGU_REG_CTRL); -+ -+ if (m->flags & DRM_MODE_FLAG_PVSYNC) -+ val |= ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST; -+ else -+ val &= ~(ARCPGU_CTRL_VS_POL_MASK << ARCPGU_CTRL_VS_POL_OFST); -+ -+ if (m->flags & DRM_MODE_FLAG_PHSYNC) -+ val |= ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST; -+ else -+ val &= ~(ARCPGU_CTRL_HS_POL_MASK << ARCPGU_CTRL_HS_POL_OFST); -+ -+ arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, val); -+ arc_pgu_write(arcpgu, ARCPGU_REG_STRIDE, 0); -+ arc_pgu_write(arcpgu, ARCPGU_REG_START_SET, 1); -+ -+ arc_pgu_set_pxl_fmt(crtc); -+ -+ clk_set_rate(arcpgu->clk, m->crtc_clock * 1000); -+} -+ -+static void arc_pgu_crtc_enable(struct drm_crtc *crtc) -+{ -+ struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); -+ -+ clk_prepare_enable(arcpgu->clk); -+ arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, -+ arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) | -+ ARCPGU_CTRL_ENABLE_MASK); -+} -+ -+static void arc_pgu_crtc_disable(struct drm_crtc *crtc) -+{ -+ struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); -+ -+ if (!crtc->primary->fb) -+ return; -+ -+ clk_disable_unprepare(arcpgu->clk); -+ arc_pgu_write(arcpgu, ARCPGU_REG_CTRL, -+ arc_pgu_read(arcpgu, ARCPGU_REG_CTRL) & -+ ~ARCPGU_CTRL_ENABLE_MASK); -+} -+ -+static int arc_pgu_crtc_atomic_check(struct drm_crtc *crtc, -+ struct drm_crtc_state *state) -+{ -+ struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); -+ struct drm_display_mode *mode = &state->adjusted_mode; -+ long rate, clk_rate = mode->clock * 1000; -+ -+ rate = clk_round_rate(arcpgu->clk, clk_rate); -+ if (rate != clk_rate) -+ return -EINVAL; -+ -+ return 0; -+} -+ -+static void arc_pgu_crtc_atomic_begin(struct drm_crtc *crtc, -+ struct drm_crtc_state *state) -+{ -+ struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); -+ unsigned long flags; -+ -+ if (crtc->state->event) { -+ struct drm_pending_vblank_event *event = crtc->state->event; -+ -+ crtc->state->event = NULL; -+ event->pipe = drm_crtc_index(crtc); -+ -+ WARN_ON(drm_crtc_vblank_get(crtc) != 0); -+ -+ spin_lock_irqsave(&crtc->dev->event_lock, flags); -+ list_add_tail(&event->base.link, &arcpgu->event_list); -+ spin_unlock_irqrestore(&crtc->dev->event_lock, flags); -+ } -+} -+ -+static const struct drm_crtc_helper_funcs arc_pgu_crtc_helper_funcs = { -+ .mode_set = drm_helper_crtc_mode_set, -+ .mode_set_base = drm_helper_crtc_mode_set_base, -+ .mode_set_nofb = arc_pgu_crtc_mode_set_nofb, -+ .enable = arc_pgu_crtc_enable, -+ .disable = arc_pgu_crtc_disable, -+ .prepare = arc_pgu_crtc_disable, -+ .commit = arc_pgu_crtc_enable, -+ .atomic_check = arc_pgu_crtc_atomic_check, -+ .atomic_begin = arc_pgu_crtc_atomic_begin, -+}; -+ -+static void arc_pgu_plane_atomic_update(struct drm_plane *plane, -+ struct drm_plane_state *state) -+{ -+ struct arcpgu_drm_private *arcpgu; -+ struct drm_gem_cma_object *gem; -+ -+ if (!plane->state->crtc || !plane->state->fb) -+ return; -+ -+ arcpgu = crtc_to_arcpgu_priv(plane->state->crtc); -+ gem = drm_fb_cma_get_gem_obj(plane->state->fb, 0); -+ arc_pgu_write(arcpgu, ARCPGU_REG_BUF0_ADDR, gem->paddr); -+} -+ -+static const struct drm_plane_helper_funcs arc_pgu_plane_helper_funcs = { -+ .prepare_fb = NULL, -+ .cleanup_fb = NULL, -+ .atomic_update = arc_pgu_plane_atomic_update, -+}; -+ -+static void arc_pgu_plane_destroy(struct drm_plane *plane) -+{ -+ drm_plane_helper_disable(plane); -+ drm_plane_cleanup(plane); -+} -+ -+static const struct drm_plane_funcs arc_pgu_plane_funcs = { -+ .update_plane = drm_atomic_helper_update_plane, -+ .disable_plane = drm_atomic_helper_disable_plane, -+ .destroy = arc_pgu_plane_destroy, -+ .reset = drm_atomic_helper_plane_reset, -+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, -+}; -+ -+static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm) -+{ -+ struct arcpgu_drm_private *arcpgu = drm->dev_private; -+ struct drm_plane *plane = NULL; -+ u32 formats[ARRAY_SIZE(supported_formats)], i; -+ int ret; -+ -+ plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL); -+ if (!plane) -+ return ERR_PTR(-ENOMEM); -+ -+ for (i = 0; i < ARRAY_SIZE(supported_formats); i++) -+ formats[i] = supported_formats[i].fourcc; -+ -+ ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs, -+ formats, ARRAY_SIZE(formats), -+ DRM_PLANE_TYPE_PRIMARY, NULL); -+ if (ret) -+ return ERR_PTR(ret); -+ -+ drm_plane_helper_add(plane, &arc_pgu_plane_helper_funcs); -+ arcpgu->plane = plane; -+ -+ return plane; -+} -+ -+int arc_pgu_setup_crtc(struct drm_device *drm) -+{ -+ struct arcpgu_drm_private *arcpgu = drm->dev_private; -+ struct drm_plane *primary; -+ int ret; -+ -+ primary = arc_pgu_plane_init(drm); -+ if (IS_ERR(primary)) -+ return PTR_ERR(primary); -+ -+ ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL, -+ &arc_pgu_crtc_funcs, NULL); -+ if (ret) { -+ arc_pgu_plane_destroy(primary); -+ return ret; -+ } -+ -+ drm_crtc_helper_add(&arcpgu->crtc, &arc_pgu_crtc_helper_funcs); -+ return 0; -+} -diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c -new file mode 100644 -index 0000000..5b35e5db ---- /dev/null -+++ b/drivers/gpu/drm/arc/arcpgu_drv.c -@@ -0,0 +1,282 @@ -+/* -+ * ARC PGU DRM driver. -+ * -+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include "arcpgu.h" -+#include "arcpgu_regs.h" -+ -+static void arcpgu_fb_output_poll_changed(struct drm_device *dev) -+{ -+ struct arcpgu_drm_private *arcpgu = dev->dev_private; -+ -+ if (arcpgu->fbdev) -+ drm_fbdev_cma_hotplug_event(arcpgu->fbdev); -+} -+ -+static int arcpgu_atomic_commit(struct drm_device *dev, -+ struct drm_atomic_state *state, bool async) -+{ -+ return drm_atomic_helper_commit(dev, state, false); -+} -+ -+static struct drm_mode_config_funcs arcpgu_drm_modecfg_funcs = { -+ .fb_create = drm_fb_cma_create, -+ .output_poll_changed = arcpgu_fb_output_poll_changed, -+ .atomic_check = drm_atomic_helper_check, -+ .atomic_commit = arcpgu_atomic_commit, -+}; -+ -+static void arcpgu_setup_mode_config(struct drm_device *drm) -+{ -+ drm_mode_config_init(drm); -+ drm->mode_config.min_width = 0; -+ drm->mode_config.min_height = 0; -+ drm->mode_config.max_width = 1920; -+ drm->mode_config.max_height = 1080; -+ drm->mode_config.funcs = &arcpgu_drm_modecfg_funcs; -+} -+ -+int arcpgu_gem_mmap(struct file *filp, struct vm_area_struct *vma) -+{ -+ int ret; -+ -+ ret = drm_gem_mmap(filp, vma); -+ if (ret) -+ return ret; -+ -+ vma->vm_page_prot = pgprot_noncached(vm_get_page_prot(vma->vm_flags)); -+ return 0; -+} -+ -+static const struct file_operations arcpgu_drm_ops = { -+ .owner = THIS_MODULE, -+ .open = drm_open, -+ .release = drm_release, -+ .unlocked_ioctl = drm_ioctl, -+#ifdef CONFIG_COMPAT -+ .compat_ioctl = drm_compat_ioctl, -+#endif -+ .poll = drm_poll, -+ .read = drm_read, -+ .llseek = no_llseek, -+ .mmap = arcpgu_gem_mmap, -+}; -+ -+static void arcpgu_preclose(struct drm_device *drm, struct drm_file *file) -+{ -+ struct arcpgu_drm_private *arcpgu = drm->dev_private; -+ struct drm_pending_vblank_event *e, *t; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&drm->event_lock, flags); -+ list_for_each_entry_safe(e, t, &arcpgu->event_list, base.link) { -+ if (e->base.file_priv != file) -+ continue; -+ list_del(&e->base.link); -+ e->base.destroy(&e->base); -+ } -+ spin_unlock_irqrestore(&drm->event_lock, flags); -+} -+ -+static void arcpgu_lastclose(struct drm_device *drm) -+{ -+ struct arcpgu_drm_private *arcpgu = drm->dev_private; -+ -+ drm_fbdev_cma_restore_mode(arcpgu->fbdev); -+} -+ -+static int arcpgu_load(struct drm_device *drm) -+{ -+ struct platform_device *pdev = to_platform_device(drm->dev); -+ struct arcpgu_drm_private *arcpgu; -+ struct device_node *encoder_node; -+ struct resource *res; -+ int ret; -+ -+ arcpgu = devm_kzalloc(&pdev->dev, sizeof(*arcpgu), GFP_KERNEL); -+ if (arcpgu == NULL) -+ return -ENOMEM; -+ -+ drm->dev_private = arcpgu; -+ -+ arcpgu->clk = devm_clk_get(drm->dev, "pxlclk"); -+ if (IS_ERR(arcpgu->clk)) -+ return PTR_ERR(arcpgu->clk); -+ -+ INIT_LIST_HEAD(&arcpgu->event_list); -+ -+ arcpgu_setup_mode_config(drm); -+ -+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -+ arcpgu->regs = devm_ioremap_resource(&pdev->dev, res); -+ if (IS_ERR(arcpgu->regs)) { -+ dev_err(drm->dev, "Could not remap IO mem\n"); -+ return PTR_ERR(arcpgu->regs); -+ } -+ -+ dev_info(drm->dev, "arc_pgu ID: 0x%x\n", -+ arc_pgu_read(arcpgu, ARCPGU_REG_ID)); -+ -+ if (dma_set_mask_and_coherent(drm->dev, DMA_BIT_MASK(32))) -+ return -ENODEV; -+ -+ if (arc_pgu_setup_crtc(drm) < 0) -+ return -ENODEV; -+ -+ /* find the encoder node and initialize it */ -+ encoder_node = of_parse_phandle(drm->dev->of_node, "encoder-slave", 0); -+ if (!encoder_node) { -+ dev_err(drm->dev, "failed to get an encoder slave node\n"); -+ return -ENODEV; -+ } -+ -+ ret = arcpgu_drm_hdmi_init(drm, encoder_node); -+ if (ret < 0) -+ return ret; -+ -+ drm_mode_config_reset(drm); -+ drm_kms_helper_poll_init(drm); -+ -+ arcpgu->fbdev = drm_fbdev_cma_init(drm, 16, -+ drm->mode_config.num_crtc, -+ drm->mode_config.num_connector); -+ if (IS_ERR(arcpgu->fbdev)) { -+ ret = PTR_ERR(arcpgu->fbdev); -+ arcpgu->fbdev = NULL; -+ return -ENODEV; -+ } -+ -+ platform_set_drvdata(pdev, arcpgu); -+ return 0; -+} -+ -+int arcpgu_unload(struct drm_device *drm) -+{ -+ struct arcpgu_drm_private *arcpgu = drm->dev_private; -+ -+ if (arcpgu->fbdev) { -+ drm_fbdev_cma_fini(arcpgu->fbdev); -+ arcpgu->fbdev = NULL; -+ } -+ drm_kms_helper_poll_fini(drm); -+ drm_vblank_cleanup(drm); -+ drm_mode_config_cleanup(drm); -+ -+ return 0; -+} -+ -+static struct drm_driver arcpgu_drm_driver = { -+ .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | -+ DRIVER_ATOMIC, -+ .preclose = arcpgu_preclose, -+ .lastclose = arcpgu_lastclose, -+ .name = "drm-arcpgu", -+ .desc = "ARC PGU Controller", -+ .date = "20160219", -+ .major = 1, -+ .minor = 0, -+ .patchlevel = 0, -+ .fops = &arcpgu_drm_ops, -+ .dumb_create = drm_gem_cma_dumb_create, -+ .dumb_map_offset = drm_gem_cma_dumb_map_offset, -+ .dumb_destroy = drm_gem_dumb_destroy, -+ .get_vblank_counter = drm_vblank_no_hw_counter, -+ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, -+ .prime_fd_to_handle = drm_gem_prime_fd_to_handle, -+ .gem_free_object = drm_gem_cma_free_object, -+ .gem_vm_ops = &drm_gem_cma_vm_ops, -+ .gem_prime_export = drm_gem_prime_export, -+ .gem_prime_import = drm_gem_prime_import, -+ .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, -+ .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, -+ .gem_prime_vmap = drm_gem_cma_prime_vmap, -+ .gem_prime_vunmap = drm_gem_cma_prime_vunmap, -+ .gem_prime_mmap = drm_gem_cma_prime_mmap, -+}; -+ -+static int arcpgu_probe(struct platform_device *pdev) -+{ -+ struct drm_device *drm; -+ int ret; -+ -+ drm = drm_dev_alloc(&arcpgu_drm_driver, &pdev->dev); -+ if (!drm) -+ return -ENOMEM; -+ -+ ret = arcpgu_load(drm); -+ if (ret) -+ goto err_unref; -+ -+ ret = drm_dev_register(drm, 0); -+ if (ret) -+ goto err_unload; -+ -+ ret = drm_connector_register_all(drm); -+ if (ret) -+ goto err_unregister; -+ -+ return 0; -+ -+err_unregister: -+ drm_dev_unregister(drm); -+ -+err_unload: -+ arcpgu_unload(drm); -+ -+err_unref: -+ drm_dev_unref(drm); -+ -+ return ret; -+} -+ -+static int arcpgu_remove(struct platform_device *pdev) -+{ -+ struct drm_device *drm = platform_get_drvdata(pdev); -+ -+ drm_connector_unregister_all(drm); -+ drm_dev_unregister(drm); -+ arcpgu_unload(drm); -+ drm_dev_unref(drm); -+ -+ return 0; -+} -+ -+static const struct of_device_id arcpgu_of_table[] = { -+ {.compatible = "snps,arcpgu"}, -+ {} -+}; -+ -+MODULE_DEVICE_TABLE(of, arcpgu_of_table); -+ -+static struct platform_driver arcpgu_platform_driver = { -+ .probe = arcpgu_probe, -+ .remove = arcpgu_remove, -+ .driver = { -+ .name = "arcpgu", -+ .of_match_table = arcpgu_of_table, -+ }, -+}; -+ -+module_platform_driver(arcpgu_platform_driver); -+ -+MODULE_AUTHOR("Carlos Palminha "); -+MODULE_DESCRIPTION("ARC PGU DRM driver"); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c -new file mode 100644 -index 0000000..08b6bae ---- /dev/null -+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c -@@ -0,0 +1,201 @@ -+/* -+ * ARC PGU DRM driver. -+ * -+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#include -+#include -+#include -+ -+#include "arcpgu.h" -+ -+struct arcpgu_drm_connector { -+ struct drm_connector connector; -+ struct drm_encoder_slave *encoder_slave; -+}; -+ -+static int arcpgu_drm_connector_get_modes(struct drm_connector *connector) -+{ -+ const struct drm_encoder_slave_funcs *sfuncs; -+ struct drm_encoder_slave *slave; -+ struct arcpgu_drm_connector *con = -+ container_of(connector, struct arcpgu_drm_connector, connector); -+ -+ slave = con->encoder_slave; -+ if (slave == NULL) { -+ dev_err(connector->dev->dev, -+ "connector_get_modes: cannot find slave encoder for connector\n"); -+ return 0; -+ } -+ -+ sfuncs = slave->slave_funcs; -+ if (sfuncs->get_modes == NULL) -+ return 0; -+ -+ return sfuncs->get_modes(&slave->base, connector); -+} -+ -+struct drm_encoder * -+arcpgu_drm_connector_best_encoder(struct drm_connector *connector) -+{ -+ struct drm_encoder_slave *slave; -+ struct arcpgu_drm_connector *con = -+ container_of(connector, struct arcpgu_drm_connector, connector); -+ -+ slave = con->encoder_slave; -+ if (slave == NULL) { -+ dev_err(connector->dev->dev, -+ "connector_best_encoder: cannot find slave encoder for connector\n"); -+ return NULL; -+ } -+ -+ return &slave->base; -+} -+ -+static enum drm_connector_status -+arcpgu_drm_connector_detect(struct drm_connector *connector, bool force) -+{ -+ enum drm_connector_status status = connector_status_unknown; -+ const struct drm_encoder_slave_funcs *sfuncs; -+ struct drm_encoder_slave *slave; -+ -+ struct arcpgu_drm_connector *con = -+ container_of(connector, struct arcpgu_drm_connector, connector); -+ -+ slave = con->encoder_slave; -+ if (slave == NULL) { -+ dev_err(connector->dev->dev, -+ "connector_detect: cannot find slave encoder for connector\n"); -+ return status; -+ } -+ -+ sfuncs = slave->slave_funcs; -+ if (sfuncs && sfuncs->detect) -+ return sfuncs->detect(&slave->base, connector); -+ -+ dev_err(connector->dev->dev, "connector_detect: could not detect slave funcs\n"); -+ return status; -+} -+ -+static void arcpgu_drm_connector_destroy(struct drm_connector *connector) -+{ -+ drm_connector_unregister(connector); -+ drm_connector_cleanup(connector); -+} -+ -+static const struct drm_connector_helper_funcs -+arcpgu_drm_connector_helper_funcs = { -+ .get_modes = arcpgu_drm_connector_get_modes, -+ .best_encoder = arcpgu_drm_connector_best_encoder, -+}; -+ -+static const struct drm_connector_funcs arcpgu_drm_connector_funcs = { -+ .dpms = drm_helper_connector_dpms, -+ .reset = drm_atomic_helper_connector_reset, -+ .detect = arcpgu_drm_connector_detect, -+ .fill_modes = drm_helper_probe_single_connector_modes, -+ .destroy = arcpgu_drm_connector_destroy, -+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, -+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -+}; -+ -+static struct drm_encoder_helper_funcs arcpgu_drm_encoder_helper_funcs = { -+ .dpms = drm_i2c_encoder_dpms, -+ .mode_fixup = drm_i2c_encoder_mode_fixup, -+ .mode_set = drm_i2c_encoder_mode_set, -+ .prepare = drm_i2c_encoder_prepare, -+ .commit = drm_i2c_encoder_commit, -+ .detect = drm_i2c_encoder_detect, -+}; -+ -+static struct drm_encoder_funcs arcpgu_drm_encoder_funcs = { -+ .destroy = drm_encoder_cleanup, -+}; -+ -+int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np) -+{ -+ struct arcpgu_drm_connector *arcpgu_connector; -+ struct drm_i2c_encoder_driver *driver; -+ struct drm_encoder_slave *encoder; -+ struct drm_connector *connector; -+ struct i2c_client *i2c_slave; -+ int ret; -+ -+ encoder = devm_kzalloc(drm->dev, sizeof(*encoder), GFP_KERNEL); -+ if (encoder == NULL) -+ return -ENOMEM; -+ -+ i2c_slave = of_find_i2c_device_by_node(np); -+ if (!i2c_slave || !i2c_get_clientdata(i2c_slave)) { -+ dev_err(drm->dev, "failed to find i2c slave encoder\n"); -+ return -EPROBE_DEFER; -+ } -+ -+ if (i2c_slave->dev.driver == NULL) { -+ dev_err(drm->dev, "failed to find i2c slave driver\n"); -+ return -EPROBE_DEFER; -+ } -+ -+ driver = -+ to_drm_i2c_encoder_driver(to_i2c_driver(i2c_slave->dev.driver)); -+ ret = driver->encoder_init(i2c_slave, drm, encoder); -+ if (ret) { -+ dev_err(drm->dev, "failed to initialize i2c encoder slave\n"); -+ return ret; -+ } -+ -+ encoder->base.possible_crtcs = 1; -+ encoder->base.possible_clones = 0; -+ ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs, -+ DRM_MODE_ENCODER_TMDS, NULL); -+ if (ret) -+ return ret; -+ -+ drm_encoder_helper_add(&encoder->base, -+ &arcpgu_drm_encoder_helper_funcs); -+ -+ arcpgu_connector = devm_kzalloc(drm->dev, sizeof(*arcpgu_connector), -+ GFP_KERNEL); -+ if (!arcpgu_connector) { -+ ret = -ENOMEM; -+ goto error_encoder_cleanup; -+ } -+ -+ connector = &arcpgu_connector->connector; -+ drm_connector_helper_add(connector, &arcpgu_drm_connector_helper_funcs); -+ ret = drm_connector_init(drm, connector, &arcpgu_drm_connector_funcs, -+ DRM_MODE_CONNECTOR_HDMIA); -+ if (ret < 0) { -+ dev_err(drm->dev, "failed to initialize drm connector\n"); -+ goto error_encoder_cleanup; -+ } -+ -+ ret = drm_mode_connector_attach_encoder(connector, &encoder->base); -+ if (ret < 0) { -+ dev_err(drm->dev, "could not attach connector to encoder\n"); -+ drm_connector_unregister(connector); -+ goto error_connector_cleanup; -+ } -+ -+ arcpgu_connector->encoder_slave = encoder; -+ -+ return 0; -+ -+error_connector_cleanup: -+ drm_connector_cleanup(connector); -+ -+error_encoder_cleanup: -+ drm_encoder_cleanup(&encoder->base); -+ return ret; -+} -diff --git a/drivers/gpu/drm/arc/arcpgu_regs.h b/drivers/gpu/drm/arc/arcpgu_regs.h -new file mode 100644 -index 0000000..95a13a8 ---- /dev/null -+++ b/drivers/gpu/drm/arc/arcpgu_regs.h -@@ -0,0 +1,40 @@ -+/* -+ * ARC PGU DRM driver. -+ * -+ * Copyright (C) 2016 Synopsys, Inc. (www.synopsys.com) -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ */ -+ -+#ifndef _ARC_PGU_REGS_H_ -+#define _ARC_PGU_REGS_H_ -+ -+#define ARCPGU_REG_CTRL 0x00 -+#define ARCPGU_REG_STAT 0x04 -+#define ARCPGU_REG_FMT 0x10 -+#define ARCPGU_REG_HSYNC 0x14 -+#define ARCPGU_REG_VSYNC 0x18 -+#define ARCPGU_REG_ACTIVE 0x1c -+#define ARCPGU_REG_BUF0_ADDR 0x40 -+#define ARCPGU_REG_STRIDE 0x50 -+#define ARCPGU_REG_START_SET 0x84 -+ -+#define ARCPGU_REG_ID 0x3FC -+ -+#define ARCPGU_CTRL_ENABLE_MASK 0x02 -+#define ARCPGU_CTRL_VS_POL_MASK 0x1 -+#define ARCPGU_CTRL_VS_POL_OFST 0x3 -+#define ARCPGU_CTRL_HS_POL_MASK 0x1 -+#define ARCPGU_CTRL_HS_POL_OFST 0x4 -+#define ARCPGU_MODE_RGB888_MASK 0x04 -+#define ARCPGU_STAT_BUSY_MASK 0x02 -+ -+#endif --- -2.5.5 - diff --git a/linux/0007-drm-arcpgu-fix-differences-with-4.4-base.patch b/linux/0007-drm-arcpgu-fix-differences-with-4.4-base.patch deleted file mode 100644 index a4743854e48..00000000000 --- a/linux/0007-drm-arcpgu-fix-differences-with-4.4-base.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 05e27a1223ff40073949fd57cb22b66c830f1b5c Mon Sep 17 00:00:00 2001 -From: Alexey Brodkin -Date: Fri, 1 Apr 2016 17:19:09 +0300 -Subject: [PATCH 7/9] drm: arcpgu: fix differences with 4.4 base - -ARC PGU driver applied before is based on top of v4.5+ -and so there're some differences functoin prototypes. - -Also in v4.4 connector_{register|unregister}_all() are missing -so adding it only in ARC PGU driver. - -Signed-off-by: Alexey Brodkin ---- - drivers/gpu/drm/arc/arcpgu_crtc.c | 4 +-- - drivers/gpu/drm/arc/arcpgu_drv.c | 58 +++++++++++++++++++++++++++++++++++++++ - drivers/gpu/drm/arc/arcpgu_hdmi.c | 2 +- - 3 files changed, 61 insertions(+), 3 deletions(-) - -diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c -index 92f8bef..5e07f28 100644 ---- a/drivers/gpu/drm/arc/arcpgu_crtc.c -+++ b/drivers/gpu/drm/arc/arcpgu_crtc.c -@@ -225,7 +225,7 @@ static struct drm_plane *arc_pgu_plane_init(struct drm_device *drm) - - ret = drm_universal_plane_init(drm, plane, 0xff, &arc_pgu_plane_funcs, - formats, ARRAY_SIZE(formats), -- DRM_PLANE_TYPE_PRIMARY, NULL); -+ DRM_PLANE_TYPE_PRIMARY); - if (ret) - return ERR_PTR(ret); - -@@ -246,7 +246,7 @@ int arc_pgu_setup_crtc(struct drm_device *drm) - return PTR_ERR(primary); - - ret = drm_crtc_init_with_planes(drm, &arcpgu->crtc, primary, NULL, -- &arc_pgu_crtc_funcs, NULL); -+ &arc_pgu_crtc_funcs); - if (ret) { - arc_pgu_plane_destroy(primary); - return ret; -diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c -index 5b35e5db..da61a33 100644 ---- a/drivers/gpu/drm/arc/arcpgu_drv.c -+++ b/drivers/gpu/drm/arc/arcpgu_drv.c -@@ -212,6 +212,64 @@ static struct drm_driver arcpgu_drm_driver = { - .gem_prime_mmap = drm_gem_cma_prime_mmap, - }; - -+/** -+ * drm_connector_unregister_all - unregister connector userspace interfaces -+ * @dev: drm device -+ * -+ * This functions unregisters all connectors from sysfs and other places so -+ * that userspace can no longer access them. Drivers should call this as the -+ * first step tearing down the device instace, or when the underlying -+ * physical device disappeared (e.g. USB unplug), right before calling -+ * drm_dev_unregister(). -+ */ -+static void drm_connector_unregister_all(struct drm_device *dev) -+{ -+ struct drm_connector *connector; -+ -+ /* FIXME: taking the mode config mutex ends up in a clash with sysfs */ -+ drm_for_each_connector(connector, dev) -+ drm_connector_unregister(connector); -+} -+ -+/** -+ * drm_connector_register_all - register all connectors -+ * @dev: drm device -+ * -+ * This function registers all connectors in sysfs and other places so that -+ * userspace can start to access them. Drivers can call it after calling -+ * drm_dev_register() to complete the device registration, if they don't call -+ * drm_connector_register() on each connector individually. -+ * -+ * When a device is unplugged and should be removed from userspace access, -+ * call drm_connector_unregister_all(), which is the inverse of this -+ * function. -+ * -+ * Returns: -+ * Zero on success, error code on failure. -+ */ -+static int drm_connector_register_all(struct drm_device *dev) -+{ -+ struct drm_connector *connector; -+ int ret; -+ -+ mutex_lock(&dev->mode_config.mutex); -+ -+ drm_for_each_connector(connector, dev) { -+ ret = drm_connector_register(connector); -+ if (ret) -+ goto err; -+ } -+ -+ mutex_unlock(&dev->mode_config.mutex); -+ -+ return 0; -+ -+err: -+ mutex_unlock(&dev->mode_config.mutex); -+ drm_connector_unregister_all(dev); -+ return ret; -+} -+ - static int arcpgu_probe(struct platform_device *pdev) - { - struct drm_device *drm; -diff --git a/drivers/gpu/drm/arc/arcpgu_hdmi.c b/drivers/gpu/drm/arc/arcpgu_hdmi.c -index 08b6bae..eb1b70d 100644 ---- a/drivers/gpu/drm/arc/arcpgu_hdmi.c -+++ b/drivers/gpu/drm/arc/arcpgu_hdmi.c -@@ -158,7 +158,7 @@ int arcpgu_drm_hdmi_init(struct drm_device *drm, struct device_node *np) - encoder->base.possible_crtcs = 1; - encoder->base.possible_clones = 0; - ret = drm_encoder_init(drm, &encoder->base, &arcpgu_drm_encoder_funcs, -- DRM_MODE_ENCODER_TMDS, NULL); -+ DRM_MODE_ENCODER_TMDS); - if (ret) - return ret; - --- -2.5.5 - diff --git a/linux/0008-arc-axs10x-add-support-of-ARC-PGU.patch b/linux/0008-arc-axs10x-add-support-of-ARC-PGU.patch deleted file mode 100644 index 4f55264e9c8..00000000000 --- a/linux/0008-arc-axs10x-add-support-of-ARC-PGU.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 505e73127a8688107779ed7c9a164a855f997252 Mon Sep 17 00:00:00 2001 -From: Alexey Brodkin -Date: Mon, 28 Mar 2016 14:36:39 +0300 -Subject: [PATCH 8/9] arc: axs10x - add support of ARC PGU - -Synopsys DesignWare ARC SDP boards sport ARC SDP display -controller attached to ADV7511 HDMI encoder. - -That change adds desctiption of both ARC PGU and ADV7511 in -ARC SDP'd base-board Device Tree. - -Signed-off-by: Alexey Brodkin -Cc: Rob Herring -Cc: Pawel Moll -Cc: Mark Rutland -Cc: Ian Campbell -Cc: Kumar Gala -Cc: Vineet Gupta -Cc: devicetree@vger.kernel.org -Cc: linux-snps-arc@lists.infradead.org ---- - arch/arc/boot/dts/axs10x_mb.dtsi | 61 ++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 61 insertions(+) - -diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi -index 44a578c..8fee596 100644 ---- a/arch/arc/boot/dts/axs10x_mb.dtsi -+++ b/arch/arc/boot/dts/axs10x_mb.dtsi -@@ -34,6 +34,12 @@ - clock-frequency = <50000000>; - #clock-cells = <0>; - }; -+ -+ pguclk: pguclk { -+ #clock-cells = <0>; -+ compatible = "fixed-clock"; -+ clock-frequency = <74440000>; -+ }; - }; - - ethernet@0x18000 { -@@ -147,6 +153,37 @@ - clocks = <&i2cclk>; - interrupts = <16>; - -+ adv7511:adv7511@39{ -+ compatible="adi,adv7511"; -+ reg = <0x39>; -+ interrupts = <23>; -+ adi,input-depth = <8>; -+ adi,input-colorspace = "rgb"; -+ adi,input-clock = "1x"; -+ adi,clock-delay = <0x03>; -+ -+ ports { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ /* RGB/YUV input */ -+ port@0 { -+ reg = <0>; -+ adv7511_input:endpoint { -+ remote-endpoint = <&pgu_output>; -+ }; -+ }; -+ -+ /* HDMI output */ -+ port@1 { -+ reg = <1>; -+ adv7511_output: endpoint { -+ remote-endpoint = <&hdmi_connector_in>; -+ }; -+ }; -+ }; -+ }; -+ - eeprom@0x54{ - compatible = "24c01"; - reg = <0x54>; -@@ -160,6 +197,16 @@ - }; - }; - -+ hdmi0: connector { -+ compatible = "hdmi-connector"; -+ type = "a"; -+ port { -+ hdmi_connector_in: endpoint { -+ remote-endpoint = <&adv7511_output>; -+ }; -+ }; -+ }; -+ - gpio0:gpio@13000 { - compatible = "snps,dw-apb-gpio"; - reg = <0x13000 0x1000>; -@@ -221,5 +268,19 @@ - reg = <2>; - }; - }; -+ -+ pgu@17000 { -+ compatible = "snps,arcpgu"; -+ reg = <0x17000 0x400>; -+ encoder-slave = <&adv7511>; -+ clocks = <&pguclk>; -+ clock-names = "pxlclk"; -+ -+ port { -+ pgu_output: endpoint { -+ remote-endpoint = <&adv7511_input>; -+ }; -+ }; -+ }; - }; - }; --- -2.5.5 - diff --git a/linux/0009-arc-axs10x-really-enable-ARC-PGU-in-defconfigs.patch b/linux/0009-arc-axs10x-really-enable-ARC-PGU-in-defconfigs.patch deleted file mode 100644 index 75258545a58..00000000000 --- a/linux/0009-arc-axs10x-really-enable-ARC-PGU-in-defconfigs.patch +++ /dev/null @@ -1,85 +0,0 @@ -From 74909c90d402ac0eaea3bbe9b2ed947d750da9e6 Mon Sep 17 00:00:00 2001 -From: Alexey Brodkin -Date: Fri, 4 Mar 2016 14:20:10 +0300 -Subject: [PATCH 9/9] arc: axs10x: really enable ARC PGU in defconfigs - -Previous patch only added device tree description and -this one adds selection of all required components in defconfgs. - -Signed-off-by: Alexey Brodkin ---- - arch/arc/boot/dts/axs101.dts | 2 +- - arch/arc/boot/dts/axs103_idu.dts | 2 +- - arch/arc/configs/axs101_defconfig | 4 ++++ - arch/arc/configs/axs103_smp_defconfig | 4 ++++ - 4 files changed, 10 insertions(+), 2 deletions(-) - -diff --git a/arch/arc/boot/dts/axs101.dts b/arch/arc/boot/dts/axs101.dts -index 3f9b058..445c3e4 100644 ---- a/arch/arc/boot/dts/axs101.dts -+++ b/arch/arc/boot/dts/axs101.dts -@@ -16,6 +16,6 @@ - compatible = "snps,axs101", "snps,arc-sdp"; - - chosen { -- bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0"; -+ bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 consoleblank=0 video=1280x720@60"; - }; - }; -diff --git a/arch/arc/boot/dts/axs103_idu.dts b/arch/arc/boot/dts/axs103_idu.dts -index f999fef..783557e 100644 ---- a/arch/arc/boot/dts/axs103_idu.dts -+++ b/arch/arc/boot/dts/axs103_idu.dts -@@ -19,6 +19,6 @@ - compatible = "snps,axs103", "snps,arc-sdp"; - - chosen { -- bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=ttyS3,115200n8 debug print-fatal-signals=1"; -+ bootargs = "earlycon=uart8250,mmio32,0xe0022000,115200n8 console=tty0 console=ttyS3,115200n8 debug print-fatal-signals=1 consoleblank=0 video=1280x720@60"; - }; - }; -diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig -index f1ac981..bc198b5 100644 ---- a/arch/arc/configs/axs101_defconfig -+++ b/arch/arc/configs/axs101_defconfig -@@ -71,12 +71,16 @@ CONFIG_SERIAL_OF_PLATFORM=y - CONFIG_I2C=y - CONFIG_I2C_CHARDEV=y - CONFIG_I2C_DESIGNWARE_PLATFORM=y -+CONFIG_DRM=y -+CONFIG_DRM_ARCPGU=y - # CONFIG_HWMON is not set - CONFIG_FB=y - # CONFIG_VGA_CONSOLE is not set - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y - CONFIG_LOGO=y -+CONFIG_DRM_FBDEV_EMULATION=y -+CONFIG_DRM_I2C_ADV7511=y - # CONFIG_LOGO_LINUX_MONO is not set - # CONFIG_LOGO_LINUX_VGA16 is not set - # CONFIG_LOGO_LINUX_CLUT224 is not set -diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig -index 66191cd..a663e62 100644 ---- a/arch/arc/configs/axs103_smp_defconfig -+++ b/arch/arc/configs/axs103_smp_defconfig -@@ -77,12 +77,16 @@ CONFIG_SERIAL_OF_PLATFORM=y - CONFIG_I2C=y - CONFIG_I2C_CHARDEV=y - CONFIG_I2C_DESIGNWARE_PLATFORM=y -+CONFIG_DRM=y -+CONFIG_DRM_ARCPGU=y - # CONFIG_HWMON is not set - CONFIG_FB=y - # CONFIG_VGA_CONSOLE is not set - CONFIG_FRAMEBUFFER_CONSOLE=y - CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y - CONFIG_LOGO=y -+CONFIG_DRM_FBDEV_EMULATION=y -+CONFIG_DRM_I2C_ADV7511=y - # CONFIG_LOGO_LINUX_MONO is not set - # CONFIG_LOGO_LINUX_VGA16 is not set - # CONFIG_LOGO_LINUX_CLUT224 is not set --- -2.5.5 -