summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2020-01-13 02:53:01 +0100
committerDave Airlie <airlied@redhat.com>2020-01-13 07:34:39 +0100
commit79f88da22b4b2d8c56c784de65e24c4b80f59c0c (patch)
tree1252dd661b5c899b8297ae8657172d9a0aae5696 /drivers/gpu/drm
parentMerge tag 'drm-misc-next-2020-01-07' of git://anongit.freedesktop.org/drm/drm... (diff)
parentdrm/panel: simple: Add Satoz SAT050AT40H12R2 panel support (diff)
downloadlinux-79f88da22b4b2d8c56c784de65e24c4b80f59c0c.tar.xz
linux-79f88da22b4b2d8c56c784de65e24c4b80f59c0c.zip
Merge tag 'drm-misc-next-2020-01-10' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for v5.6: UAPI Changes: Cross-subsystem Changes: - Convert simple panel bindings to a template. Core Changes: - Revert drm-bridge-state changes, it causes a dependency error between drm and drm_kms_helper. - Fix when disabling crc's. - Assorted Kconfig fixes. Driver Changes: - Add ddc symlinks to more drivers. - Fix chained bridge handling in exynos and vc4. - More clock rate fixes in sun4i. - Add support for AUO B116XAK01, GiantPlus GPM940B0, Sony ACX424AKP, BOE NV140FHM-N49, Satoz SAT050AT40H12R2 and Sharp LS020B1DD01D panels. - Assorted small bugfixes. Signed-off-by: Dave Airlie <airlied@redhat.com> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/1e8d4944-68d7-0df3-f39b-31f6fba22a2a@linux.intel.com
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/Kconfig1
-rw-r--r--drivers/gpu/drm/bridge/analogix/analogix_dp_core.c41
-rw-r--r--drivers/gpu/drm/drm_atomic.c39
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c32
-rw-r--r--drivers/gpu/drm/drm_bridge.c527
-rw-r--r--drivers/gpu/drm/drm_debugfs_crc.c9
-rw-r--r--drivers/gpu/drm/drm_fb_cma_helper.c1
-rw-r--r--drivers/gpu/drm/drm_lock.c3
-rw-r--r--drivers/gpu/drm/drm_modes.c9
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c29
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.c3
-rw-r--r--drivers/gpu/drm/lima/lima_sched.c35
-rw-r--r--drivers/gpu/drm/lima/lima_sched.h2
-rw-r--r--drivers/gpu/drm/meson/meson_drv.h2
-rw-r--r--drivers/gpu/drm/meson/meson_rdma.c12
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c3
-rw-r--r--drivers/gpu/drm/panel/Kconfig11
-rw-r--r--drivers/gpu/drm/panel/Makefile1
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c94
-rw-r--r--drivers/gpu/drm/panel/panel-sony-acx424akp.c550
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_lvds.c8
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c9
-rw-r--r--drivers/gpu/drm/sun4i/sun6i_drc.c8
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c7
-rw-r--r--drivers/gpu/drm/tegra/sor.c7
-rw-r--r--drivers/gpu/drm/udl/Kconfig3
-rw-r--r--drivers/gpu/drm/vc4/vc4_dsi.c28
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c12
-rw-r--r--drivers/gpu/drm/zte/zx_hdmi.c6
-rw-r--r--drivers/gpu/drm/zte/zx_vga.c6
30 files changed, 822 insertions, 676 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 7041323a7bff..d0aa6cff2e02 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -168,6 +168,7 @@ config DRM_LOAD_EDID_FIRMWARE
config DRM_DP_CEC
bool "Enable DisplayPort CEC-Tunneling-over-AUX HDMI support"
+ depends on DRM
select CEC_CORE
help
Choose this option if you want to enable HDMI CEC support for
diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
index 6fab71985cd4..6effe532f820 100644
--- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
+++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
@@ -1289,21 +1289,19 @@ struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp,
return conn_state->crtc;
}
-static void
-analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+static void analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state)
{
- struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int ret;
- crtc = analogix_dp_get_new_crtc(dp, old_state);
+ crtc = analogix_dp_get_new_crtc(dp, state);
if (!crtc)
return;
- old_crtc_state = drm_atomic_get_old_crtc_state(old_state, crtc);
+ old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
/* Don't touch the panel if we're coming back from PSR */
if (old_crtc_state && old_crtc_state->self_refresh_active)
return;
@@ -1368,22 +1366,20 @@ out_dp_clk_pre:
return ret;
}
-static void
-analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+static void analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state)
{
- struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int timeout_loop = 0;
int ret;
- crtc = analogix_dp_get_new_crtc(dp, old_state);
+ crtc = analogix_dp_get_new_crtc(dp, state);
if (!crtc)
return;
- old_crtc_state = drm_atomic_get_old_crtc_state(old_state, crtc);
+ old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
/* Not a full enable, just disable PSR and continue */
if (old_crtc_state && old_crtc_state->self_refresh_active) {
ret = analogix_dp_disable_psr(dp);
@@ -1444,20 +1440,18 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge)
dp->dpms_mode = DRM_MODE_DPMS_OFF;
}
-static void
-analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state)
{
- struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state = NULL;
- crtc = analogix_dp_get_new_crtc(dp, old_state);
+ crtc = analogix_dp_get_new_crtc(dp, state);
if (!crtc)
goto out;
- new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc);
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
if (!new_crtc_state)
goto out;
@@ -1469,21 +1463,20 @@ out:
analogix_dp_bridge_disable(bridge);
}
-static void
-analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+static
+void analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge,
+ struct drm_atomic_state *state)
{
- struct drm_atomic_state *old_state = old_bridge_state->base.state;
struct analogix_dp_device *dp = bridge->driver_private;
struct drm_crtc *crtc;
struct drm_crtc_state *new_crtc_state;
int ret;
- crtc = analogix_dp_get_new_crtc(dp, old_state);
+ crtc = analogix_dp_get_new_crtc(dp, state);
if (!crtc)
return;
- new_crtc_state = drm_atomic_get_new_crtc_state(old_state, crtc);
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
if (!new_crtc_state || !new_crtc_state->self_refresh_active)
return;
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index bf1b9c37d515..d33691512a8e 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -30,7 +30,6 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
-#include <drm/drm_bridge.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
@@ -1019,44 +1018,6 @@ static void drm_atomic_connector_print_state(struct drm_printer *p,
}
/**
- * drm_atomic_add_encoder_bridges - add bridges attached to an encoder
- * @state: atomic state
- * @encoder: DRM encoder
- *
- * This function adds all bridges attached to @encoder. This is needed to add
- * bridge states to @state and make them available when
- * &bridge_funcs.atomic_{check,pre_enable,enable,disable_post_disable}() are
- * called
- *
- * Returns:
- * 0 on success or can fail with -EDEADLK or -ENOMEM. When the error is EDEADLK
- * then the w/w mutex code has detected a deadlock and the entire atomic
- * sequence must be restarted. All other errors are fatal.
- */
-int
-drm_atomic_add_encoder_bridges(struct drm_atomic_state *state,
- struct drm_encoder *encoder)
-{
- struct drm_bridge_state *bridge_state;
- struct drm_bridge *bridge;
-
- if (!encoder)
- return 0;
-
- DRM_DEBUG_ATOMIC("Adding all bridges for [encoder:%d:%s] to %p\n",
- encoder->base.id, encoder->name, state);
-
- drm_for_each_bridge_in_chain(encoder, bridge) {
- bridge_state = drm_atomic_get_bridge_state(state, bridge);
- if (IS_ERR(bridge_state))
- return PTR_ERR(bridge_state);
- }
-
- return 0;
-}
-EXPORT_SYMBOL(drm_atomic_add_encoder_bridges);
-
-/**
* drm_atomic_add_affected_connectors - add connectors for CRTC
* @state: atomic state
* @crtc: DRM CRTC
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index afe14f72a824..4511c2e07bb9 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -437,12 +437,12 @@ mode_fixup(struct drm_atomic_state *state)
funcs = encoder->helper_private;
bridge = drm_bridge_chain_get_first_bridge(encoder);
- ret = drm_atomic_bridge_chain_check(bridge,
- new_crtc_state,
- new_conn_state);
- if (ret) {
- DRM_DEBUG_ATOMIC("Bridge atomic check failed\n");
- return ret;
+ ret = drm_bridge_chain_mode_fixup(bridge,
+ &new_crtc_state->mode,
+ &new_crtc_state->adjusted_mode);
+ if (!ret) {
+ DRM_DEBUG_ATOMIC("Bridge fixup failed\n");
+ return -EINVAL;
}
if (funcs && funcs->atomic_check) {
@@ -730,26 +730,6 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
return ret;
}
- /*
- * Iterate over all connectors again, and add all affected bridges to
- * the state.
- */
- for_each_oldnew_connector_in_state(state, connector,
- old_connector_state,
- new_connector_state, i) {
- struct drm_encoder *encoder;
-
- encoder = old_connector_state->best_encoder;
- ret = drm_atomic_add_encoder_bridges(state, encoder);
- if (ret)
- return ret;
-
- encoder = new_connector_state->best_encoder;
- ret = drm_atomic_add_encoder_bridges(state, encoder);
- if (ret)
- return ret;
- }
-
ret = mode_valid(state);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c
index 37400607e9b7..c2cf0c90fa26 100644
--- a/drivers/gpu/drm/drm_bridge.c
+++ b/drivers/gpu/drm/drm_bridge.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
-#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_encoder.h>
@@ -90,74 +89,6 @@ void drm_bridge_remove(struct drm_bridge *bridge)
}
EXPORT_SYMBOL(drm_bridge_remove);
-static struct drm_bridge_state *
-drm_atomic_default_bridge_duplicate_state(struct drm_bridge *bridge)
-{
- struct drm_bridge_state *new;
-
- if (WARN_ON(!bridge->base.state))
- return NULL;
-
- new = kzalloc(sizeof(*new), GFP_KERNEL);
- if (new)
- __drm_atomic_helper_bridge_duplicate_state(bridge, new);
-
- return new;
-}
-
-static struct drm_private_state *
-drm_bridge_atomic_duplicate_priv_state(struct drm_private_obj *obj)
-{
- struct drm_bridge *bridge = drm_priv_to_bridge(obj);
- struct drm_bridge_state *state;
-
- if (bridge->funcs->atomic_duplicate_state)
- state = bridge->funcs->atomic_duplicate_state(bridge);
- else
- state = drm_atomic_default_bridge_duplicate_state(bridge);
-
- return state ? &state->base : NULL;
-}
-
-static void
-drm_atomic_default_bridge_destroy_state(struct drm_bridge *bridge,
- struct drm_bridge_state *state)
-{
- /* Just a simple kfree() for now */
- kfree(state);
-}
-
-static void
-drm_bridge_atomic_destroy_priv_state(struct drm_private_obj *obj,
- struct drm_private_state *s)
-{
- struct drm_bridge_state *state = drm_priv_to_bridge_state(s);
- struct drm_bridge *bridge = drm_priv_to_bridge(obj);
-
- if (bridge->funcs->atomic_destroy_state)
- bridge->funcs->atomic_destroy_state(bridge, state);
- else
- drm_atomic_default_bridge_destroy_state(bridge, state);
-}
-
-static const struct drm_private_state_funcs drm_bridge_priv_state_funcs = {
- .atomic_duplicate_state = drm_bridge_atomic_duplicate_priv_state,
- .atomic_destroy_state = drm_bridge_atomic_destroy_priv_state,
-};
-
-static struct drm_bridge_state *
-drm_atomic_default_bridge_reset(struct drm_bridge *bridge)
-{
- struct drm_bridge_state *bridge_state;
-
- bridge_state = kzalloc(sizeof(*bridge_state), GFP_KERNEL);
- if (!bridge_state)
- return ERR_PTR(-ENOMEM);
-
- __drm_atomic_helper_bridge_reset(bridge, bridge_state);
- return bridge_state;
-}
-
/**
* drm_bridge_attach - attach the bridge to an encoder's chain
*
@@ -183,7 +114,6 @@ drm_atomic_default_bridge_reset(struct drm_bridge *bridge)
int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
struct drm_bridge *previous)
{
- struct drm_bridge_state *state;
int ret;
if (!encoder || !bridge)
@@ -205,35 +135,15 @@ int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge,
if (bridge->funcs->attach) {
ret = bridge->funcs->attach(bridge);
- if (ret < 0)
- goto err_reset_bridge;
- }
-
- if (bridge->funcs->atomic_reset)
- state = bridge->funcs->atomic_reset(bridge);
- else
- state = drm_atomic_default_bridge_reset(bridge);
-
- if (IS_ERR(state)) {
- ret = PTR_ERR(state);
- goto err_detach_bridge;
+ if (ret < 0) {
+ list_del(&bridge->chain_node);
+ bridge->dev = NULL;
+ bridge->encoder = NULL;
+ return ret;
+ }
}
- drm_atomic_private_obj_init(bridge->dev, &bridge->base,
- &state->base,
- &drm_bridge_priv_state_funcs);
-
return 0;
-
-err_detach_bridge:
- if (bridge->funcs->detach)
- bridge->funcs->detach(bridge);
-
-err_reset_bridge:
- bridge->dev = NULL;
- bridge->encoder = NULL;
- list_del(&bridge->chain_node);
- return ret;
}
EXPORT_SYMBOL(drm_bridge_attach);
@@ -245,8 +155,6 @@ void drm_bridge_detach(struct drm_bridge *bridge)
if (WARN_ON(!bridge->dev))
return;
- drm_atomic_private_obj_fini(&bridge->base);
-
if (bridge->funcs->detach)
bridge->funcs->detach(bridge);
@@ -501,19 +409,10 @@ void drm_atomic_bridge_chain_disable(struct drm_bridge *bridge,
encoder = bridge->encoder;
list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
- if (iter->funcs->atomic_disable) {
- struct drm_bridge_state *old_bridge_state;
-
- old_bridge_state =
- drm_atomic_get_old_bridge_state(old_state,
- iter);
- if (WARN_ON(!old_bridge_state))
- return;
-
- iter->funcs->atomic_disable(iter, old_bridge_state);
- } else if (iter->funcs->disable) {
+ if (iter->funcs->atomic_disable)
+ iter->funcs->atomic_disable(iter, old_state);
+ else if (iter->funcs->disable)
iter->funcs->disable(iter);
- }
if (iter == bridge)
break;
@@ -544,20 +443,10 @@ void drm_atomic_bridge_chain_post_disable(struct drm_bridge *bridge,
encoder = bridge->encoder;
list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
- if (bridge->funcs->atomic_post_disable) {
- struct drm_bridge_state *old_bridge_state;
-
- old_bridge_state =
- drm_atomic_get_old_bridge_state(old_state,
- bridge);
- if (WARN_ON(!old_bridge_state))
- return;
-
- bridge->funcs->atomic_post_disable(bridge,
- old_bridge_state);
- } else if (bridge->funcs->post_disable) {
+ if (bridge->funcs->atomic_post_disable)
+ bridge->funcs->atomic_post_disable(bridge, old_state);
+ else if (bridge->funcs->post_disable)
bridge->funcs->post_disable(bridge);
- }
}
}
EXPORT_SYMBOL(drm_atomic_bridge_chain_post_disable);
@@ -586,19 +475,10 @@ void drm_atomic_bridge_chain_pre_enable(struct drm_bridge *bridge,
encoder = bridge->encoder;
list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
- if (iter->funcs->atomic_pre_enable) {
- struct drm_bridge_state *old_bridge_state;
-
- old_bridge_state =
- drm_atomic_get_old_bridge_state(old_state,
- iter);
- if (WARN_ON(!old_bridge_state))
- return;
-
- iter->funcs->atomic_pre_enable(iter, old_bridge_state);
- } else if (iter->funcs->pre_enable) {
+ if (iter->funcs->atomic_pre_enable)
+ iter->funcs->atomic_pre_enable(iter, old_state);
+ else if (iter->funcs->pre_enable)
iter->funcs->pre_enable(iter);
- }
if (iter == bridge)
break;
@@ -628,385 +508,14 @@ void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge,
encoder = bridge->encoder;
list_for_each_entry_from(bridge, &encoder->bridge_chain, chain_node) {
- if (bridge->funcs->atomic_enable) {
- struct drm_bridge_state *old_bridge_state;
-
- old_bridge_state =
- drm_atomic_get_old_bridge_state(old_state,
- bridge);
- if (WARN_ON(!old_bridge_state))
- return;
-
- bridge->funcs->atomic_enable(bridge, old_bridge_state);
- } else if (bridge->funcs->enable) {
+ if (bridge->funcs->atomic_enable)
+ bridge->funcs->atomic_enable(bridge, old_state);
+ else if (bridge->funcs->enable)
bridge->funcs->enable(bridge);
- }
}
}
EXPORT_SYMBOL(drm_atomic_bridge_chain_enable);
-static int drm_atomic_bridge_check(struct drm_bridge *bridge,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
-{
- if (bridge->funcs->atomic_check) {
- struct drm_bridge_state *bridge_state;
- int ret;
-
- bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
- bridge);
- if (WARN_ON(!bridge_state))
- return -EINVAL;
-
- ret = bridge->funcs->atomic_check(bridge, bridge_state,
- crtc_state, conn_state);
- if (ret)
- return ret;
- } else if (bridge->funcs->mode_fixup) {
- if (!bridge->funcs->mode_fixup(bridge, &crtc_state->mode,
- &crtc_state->adjusted_mode))
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * drm_atomic_helper_bridge_propagate_bus_fmt() - Propagate output format to
- * the input end of a bridge
- * @bridge: bridge control structure
- * @bridge_state: new bridge state
- * @crtc_state: new CRTC state
- * @conn_state: new connector state
- * @output_fmt: tested output bus format
- * @num_input_fmts: will contain the size of the returned array
- *
- * This helper is a pluggable implementation of the
- * &drm_bridge_funcs.atomic_get_input_bus_fmts operation for bridges that don't
- * modify the bus configuration between their input and their output. It
- * returns an array of input formats with a single element set to @output_fmt.
- *
- * RETURNS:
- * a valid format array of size @num_input_fmts, or NULL if the allocation
- * failed
- */
-u32 *
-drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge,
- struct drm_bridge_state *bridge_state,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state,
- u32 output_fmt,
- unsigned int *num_input_fmts)
-{
- u32 *input_fmts;
-
- input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL);
- if (!input_fmts) {
- *num_input_fmts = 0;
- return NULL;
- }
-
- *num_input_fmts = 1;
- input_fmts[0] = output_fmt;
- return input_fmts;
-}
-EXPORT_SYMBOL(drm_atomic_helper_bridge_propagate_bus_fmt);
-
-static int select_bus_fmt_recursive(struct drm_bridge *first_bridge,
- struct drm_bridge *cur_bridge,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state,
- u32 out_bus_fmt)
-{
- struct drm_bridge_state *cur_state;
- unsigned int num_in_bus_fmts, i;
- struct drm_bridge *prev_bridge;
- u32 *in_bus_fmts;
- int ret;
-
- prev_bridge = drm_bridge_get_prev_bridge(cur_bridge);
- cur_state = drm_atomic_get_new_bridge_state(crtc_state->state,
- cur_bridge);
- if (WARN_ON(!cur_state))
- return -EINVAL;
-
- /*
- * If bus format negotiation is not supported by this bridge, let's
- * pass MEDIA_BUS_FMT_FIXED to the previous bridge in the chain and
- * hope that it can handle this situation gracefully (by providing
- * appropriate default values).
- */
- if (!cur_bridge->funcs->atomic_get_input_bus_fmts) {
- if (cur_bridge != first_bridge) {
- ret = select_bus_fmt_recursive(first_bridge,
- prev_bridge, crtc_state,
- conn_state,
- MEDIA_BUS_FMT_FIXED);
- if (ret)
- return ret;
- }
-
- cur_state->input_bus_cfg.format = MEDIA_BUS_FMT_FIXED;
- cur_state->output_bus_cfg.format = out_bus_fmt;
- return 0;
- }
-
- in_bus_fmts = cur_bridge->funcs->atomic_get_input_bus_fmts(cur_bridge,
- cur_state,
- crtc_state,
- conn_state,
- out_bus_fmt,
- &num_in_bus_fmts);
- if (!num_in_bus_fmts)
- return -ENOTSUPP;
- else if (!in_bus_fmts)
- return -ENOMEM;
-
- if (first_bridge == cur_bridge) {
- cur_state->input_bus_cfg.format = in_bus_fmts[0];
- cur_state->output_bus_cfg.format = out_bus_fmt;
- kfree(in_bus_fmts);
- return 0;
- }
-
- for (i = 0; i < num_in_bus_fmts; i++) {
- ret = select_bus_fmt_recursive(first_bridge, prev_bridge,
- crtc_state, conn_state,
- in_bus_fmts[i]);
- if (ret != -ENOTSUPP)
- break;
- }
-
- if (!ret) {
- cur_state->input_bus_cfg.format = in_bus_fmts[i];
- cur_state->output_bus_cfg.format = out_bus_fmt;
- }
-
- kfree(in_bus_fmts);
- return ret;
-}
-
-/*
- * This function is called by &drm_atomic_bridge_chain_check() just before
- * calling &drm_bridge_funcs.atomic_check() on all elements of the chain.
- * It performs bus format negotiation between bridge elements. The negotiation
- * happens in reverse order, starting from the last element in the chain up to
- * @bridge.
- *
- * Negotiation starts by retrieving supported output bus formats on the last
- * bridge element and testing them one by one. The test is recursive, meaning
- * that for each tested output format, the whole chain will be walked backward,
- * and each element will have to choose an input bus format that can be
- * transcoded to the requested output format. When a bridge element does not
- * support transcoding into a specific output format -ENOTSUPP is returned and
- * the next bridge element will have to try a different format. If none of the
- * combinations worked, -ENOTSUPP is returned and the atomic modeset will fail.
- *
- * This implementation is relying on
- * &drm_bridge_funcs.atomic_get_output_bus_fmts() and
- * &drm_bridge_funcs.atomic_get_input_bus_fmts() to gather supported
- * input/output formats.
- *
- * When &drm_bridge_funcs.atomic_get_output_bus_fmts() is not implemented by
- * the last element of the chain, &drm_atomic_bridge_chain_select_bus_fmts()
- * tries a single format: &drm_connector.display_info.bus_formats[0] if
- * available, MEDIA_BUS_FMT_FIXED otherwise.
- *
- * When &drm_bridge_funcs.atomic_get_input_bus_fmts() is not implemented,
- * &drm_atomic_bridge_chain_select_bus_fmts() skips the negotiation on the
- * bridge element that lacks this hook and asks the previous element in the
- * chain to try MEDIA_BUS_FMT_FIXED. It's up to bridge drivers to decide what
- * to do in that case (fail if they want to enforce bus format negotiation, or
- * provide a reasonable default if they need to support pipelines where not
- * all elements support bus format negotiation).
- */
-static int
-drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
-{
- struct drm_connector *conn = conn_state->connector;
- struct drm_encoder *encoder = bridge->encoder;
- struct drm_bridge_state *last_bridge_state;
- unsigned int i, num_out_bus_fmts;
- struct drm_bridge *last_bridge;
- u32 *out_bus_fmts;
- int ret = 0;
-
- last_bridge = list_last_entry(&encoder->bridge_chain,
- struct drm_bridge, chain_node);
- last_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state,
- last_bridge);
- if (WARN_ON(!last_bridge_state))
- return -EINVAL;
-
- if (last_bridge->funcs->atomic_get_output_bus_fmts) {
- const struct drm_bridge_funcs *funcs = last_bridge->funcs;
-
- out_bus_fmts = funcs->atomic_get_output_bus_fmts(last_bridge,
- last_bridge_state,
- crtc_state,
- conn_state,
- &num_out_bus_fmts);
- if (!num_out_bus_fmts)
- return -ENOTSUPP;
- else if (!out_bus_fmts)
- return -ENOMEM;
- } else {
- num_out_bus_fmts = 1;
- out_bus_fmts = kmalloc(sizeof(*out_bus_fmts), GFP_KERNEL);
- if (!out_bus_fmts)
- return -ENOMEM;
-
- if (conn->display_info.num_bus_formats &&
- conn->display_info.bus_formats)
- out_bus_fmts[0] = conn->display_info.bus_formats[0];
- else
- out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED;
- }
-
- for (i = 0; i < num_out_bus_fmts; i++) {
- ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state,
- conn_state, out_bus_fmts[i]);
- if (ret != -ENOTSUPP)
- break;
- }
-
- kfree(out_bus_fmts);
-
- return ret;
-}
-
-static void
-drm_atomic_bridge_propagate_bus_flags(struct drm_bridge *bridge,
- struct drm_connector *conn,
- struct drm_atomic_state *state)
-{
- struct drm_bridge_state *bridge_state, *next_bridge_state;
- struct drm_bridge *next_bridge;
- u32 output_flags;
-
- bridge_state = drm_atomic_get_new_bridge_state(state, bridge);
- next_bridge = drm_bridge_get_next_bridge(bridge);
-
- /*
- * Let's try to apply the most common case here, that is, propagate
- * display_info flags for the last bridge, and propagate the input
- * flags of the next bridge element to the output end of the current
- * bridge when the bridge is not the last one.
- * There are exceptions to this rule, like when signal inversion is
- * happening at the board level, but that's something drivers can deal
- * with from their &drm_bridge_funcs.atomic_check() implementation by
- * simply overriding the flags value we've set here.
- */
- if (!next_bridge) {
- output_flags = conn->display_info.bus_flags;
- } else {
- next_bridge_state = drm_atomic_get_new_bridge_state(state,
- next_bridge);
- output_flags = next_bridge_state->input_bus_cfg.flags;
- }
-
- bridge_state->output_bus_cfg.flags = output_flags;
-
- /*
- * Propage the output flags to the input end of the bridge. Again, it's
- * not necessarily what all bridges want, but that's what most of them
- * do, and by doing that by default we avoid forcing drivers to
- * duplicate the "dummy propagation" logic.
- */
- bridge_state->input_bus_cfg.flags = output_flags;
-}
-
-/**
- * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain
- * @bridge: bridge control structure
- * @crtc_state: new CRTC state
- * @conn_state: new connector state
- *
- * First trigger a bus format negotiation before calling
- * &drm_bridge_funcs.atomic_check() (falls back on
- * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain,
- * starting from the last bridge to the first. These are called before calling
- * &drm_encoder_helper_funcs.atomic_check()
- *
- * RETURNS:
- * 0 on success, a negative error code on failure
- */
-int drm_atomic_bridge_chain_check(struct drm_bridge *bridge,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
-{
- struct drm_connector *conn = conn_state->connector;
- struct drm_encoder *encoder = bridge->encoder;
- struct drm_bridge *iter;
- int ret;
-
- ret = drm_atomic_bridge_chain_select_bus_fmts(bridge, crtc_state,
- conn_state);
- if (ret)
- return ret;
-
- list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) {
- int ret;
-
- /*
- * Bus flags are propagated by default. If a bridge needs to
- * tweak the input bus flags for any reason, it should happen
- * in its &drm_bridge_funcs.atomic_check() implementation such
- * that preceding bridges in the chain can propagate the new
- * bus flags.
- */
- drm_atomic_bridge_propagate_bus_flags(iter, conn,
- crtc_state->state);
-
- ret = drm_atomic_bridge_check(iter, crtc_state, conn_state);
- if (ret)
- return ret;
-
- if (iter == bridge)
- break;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(drm_atomic_bridge_chain_check);
-
-/**
- * __drm_atomic_helper_bridge_reset() - Initialize a bridge state to its
- * default
- * @bridge: the bridge this state is refers to
- * @state: bridge state to initialize
- *
- * Initialize the bridge state to default values. This is meant to be* called
- * by the bridge &drm_plane_funcs.reset hook for bridges that subclass the
- * bridge state.
- */
-void __drm_atomic_helper_bridge_reset(struct drm_bridge *bridge,
- struct drm_bridge_state *state)
-{
- memset(state, 0, sizeof(*state));
- state->bridge = bridge;
-}
-EXPORT_SYMBOL(__drm_atomic_helper_bridge_reset);
-
-/**
- * __drm_atomic_helper_bridge_duplicate_state() - Copy atomic bridge state
- * @bridge: bridge object
- * @state: atomic bridge state
- *
- * Copies atomic state from a bridge's current state and resets inferred values.
- * This is useful for drivers that subclass the bridge state.
- */
-void __drm_atomic_helper_bridge_duplicate_state(struct drm_bridge *bridge,
- struct drm_bridge_state *state)
-{
- __drm_atomic_helper_private_obj_duplicate_state(&bridge->base,
- &state->base);
- state->bridge = bridge;
-}
-EXPORT_SYMBOL(__drm_atomic_helper_bridge_duplicate_state);
-
#ifdef CONFIG_OF
/**
* of_drm_find_bridge - find the bridge corresponding to the device node in
diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c
index ca3c55c6b815..e22b812c4b80 100644
--- a/drivers/gpu/drm/drm_debugfs_crc.c
+++ b/drivers/gpu/drm/drm_debugfs_crc.c
@@ -140,8 +140,8 @@ static ssize_t crc_control_write(struct file *file, const char __user *ubuf,
if (IS_ERR(source))
return PTR_ERR(source);
- if (source[len] == '\n')
- source[len] = '\0';
+ if (source[len - 1] == '\n')
+ source[len - 1] = '\0';
ret = crtc->funcs->verify_crc_source(crtc, source, &values_cnt);
if (ret)
@@ -258,6 +258,11 @@ static int crtc_crc_release(struct inode *inode, struct file *filep)
struct drm_crtc *crtc = filep->f_inode->i_private;
struct drm_crtc_crc *crc = &crtc->crc;
+ /* terminate the infinite while loop if 'drm_dp_aux_crc_work' running */
+ spin_lock_irq(&crc->lock);
+ crc->opened = false;
+ spin_unlock_irq(&crc->lock);
+
crtc->funcs->set_crc_source(crtc, NULL);
spin_lock_irq(&crc->lock);
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index c0b0f603af63..9801c0333eca 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -9,6 +9,7 @@
* Copyright (C) 2012 Red Hat
*/
+#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_cma_helper.h>
diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c
index 2e8ce99d0baa..2c79e8199e3c 100644
--- a/drivers/gpu/drm/drm_lock.c
+++ b/drivers/gpu/drm/drm_lock.c
@@ -360,7 +360,8 @@ void drm_legacy_lock_master_cleanup(struct drm_device *dev, struct drm_master *m
/*
* Since the master is disappearing, so is the
* possibility to lock.
- */ mutex_lock(&dev->struct_mutex);
+ */
+ mutex_lock(&dev->struct_mutex);
if (master->lock.hw_lock) {
if (dev->sigdata.lock == master->lock.hw_lock)
dev->sigdata.lock = NULL;
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 2a4eb619d7ad..10336b144c72 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -233,7 +233,7 @@ struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay,
/* 3) Nominal HSync width (% of line period) - default 8 */
#define CVT_HSYNC_PERCENTAGE 8
unsigned int hblank_percentage;
- int vsyncandback_porch, vback_porch, hblank;
+ int vsyncandback_porch, __maybe_unused vback_porch, hblank;
/* estimated the horizontal period */
tmp1 = HV_FACTOR * 1000000 -
@@ -386,9 +386,10 @@ drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay,
int top_margin, bottom_margin;
int interlace;
unsigned int hfreq_est;
- int vsync_plus_bp, vback_porch;
- unsigned int vtotal_lines, vfieldrate_est, hperiod;
- unsigned int vfield_rate, vframe_rate;
+ int vsync_plus_bp, __maybe_unused vback_porch;
+ unsigned int vtotal_lines, __maybe_unused vfieldrate_est;
+ unsigned int __maybe_unused hperiod;
+ unsigned int vfield_rate, __maybe_unused vframe_rate;
int left_margin, right_margin;
unsigned int total_active_pixels, ideal_duty_cycle;
unsigned int hblank, total_pixels, pixel_freq;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 3955f84dc893..33628d85edad 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1378,6 +1378,7 @@ static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
static void exynos_dsi_enable(struct drm_encoder *encoder)
{
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
+ struct drm_bridge *iter;
int ret;
if (dsi->state & DSIM_STATE_ENABLED)
@@ -1391,7 +1392,11 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
if (ret < 0)
goto err_put_sync;
} else {
- drm_bridge_chain_pre_enable(dsi->out_bridge);
+ list_for_each_entry_reverse(iter, &dsi->bridge_chain,
+ chain_node) {
+ if (iter->funcs->pre_enable)
+ iter->funcs->pre_enable(iter);
+ }
}
exynos_dsi_set_display_mode(dsi);
@@ -1402,7 +1407,10 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
if (ret < 0)
goto err_display_disable;
} else {
- drm_bridge_chain_enable(dsi->out_bridge);
+ list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
+ if (iter->funcs->enable)
+ iter->funcs->enable(iter);
+ }
}
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
@@ -1420,6 +1428,7 @@ err_put_sync:
static void exynos_dsi_disable(struct drm_encoder *encoder)
{
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
+ struct drm_bridge *iter;
if (!(dsi->state & DSIM_STATE_ENABLED))
return;
@@ -1427,10 +1436,20 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
drm_panel_disable(dsi->panel);
- drm_bridge_chain_disable(dsi->out_bridge);
+
+ list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
+ if (iter->funcs->disable)
+ iter->funcs->disable(iter);
+ }
+
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
- drm_bridge_chain_post_disable(dsi->out_bridge);
+
+ list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
+ if (iter->funcs->post_disable)
+ iter->funcs->post_disable(iter);
+ }
+
dsi->state &= ~DSIM_STATE_ENABLED;
pm_runtime_put_sync(dsi->dev);
}
@@ -1523,7 +1542,7 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
if (out_bridge) {
drm_bridge_attach(encoder, out_bridge, NULL);
dsi->out_bridge = out_bridge;
- list_splice(&encoder->bridge_chain, &dsi->bridge_chain);
+ list_splice_init(&encoder->bridge_chain, &dsi->bridge_chain);
} else {
int ret = exynos_dsi_create_connector(encoder);
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
index 40a37e400b02..91f90016dba9 100644
--- a/drivers/gpu/drm/gma500/psb_irq.c
+++ b/drivers/gpu/drm/gma500/psb_irq.c
@@ -470,12 +470,11 @@ void psb_irq_turn_off_dpst(struct drm_device *dev)
{
struct drm_psb_private *dev_priv =
(struct drm_psb_private *) dev->dev_private;
- u32 hist_reg;
u32 pwm_reg;
if (gma_power_begin(dev, false)) {
PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
- hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
+ PSB_RVDC32(HISTOGRAM_INT_CONTROL);
psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
index f522c5f99729..a31a90c380b6 100644
--- a/drivers/gpu/drm/lima/lima_sched.c
+++ b/drivers/gpu/drm/lima/lima_sched.c
@@ -255,13 +255,17 @@ static struct dma_fence *lima_sched_run_job(struct drm_sched_job *job)
return task->fence;
}
-static void lima_sched_handle_error_task(struct lima_sched_pipe *pipe,
- struct lima_sched_task *task)
+static void lima_sched_timedout_job(struct drm_sched_job *job)
{
+ struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
+ struct lima_sched_task *task = to_lima_task(job);
+
+ if (!pipe->error)
+ DRM_ERROR("lima job timeout\n");
+
drm_sched_stop(&pipe->base, &task->base);
- if (task)
- drm_sched_increase_karma(&task->base);
+ drm_sched_increase_karma(&task->base);
pipe->task_error(pipe);
@@ -284,16 +288,6 @@ static void lima_sched_handle_error_task(struct lima_sched_pipe *pipe,
drm_sched_start(&pipe->base, true);
}
-static void lima_sched_timedout_job(struct drm_sched_job *job)
-{
- struct lima_sched_pipe *pipe = to_lima_pipe(job->sched);
- struct lima_sched_task *task = to_lima_task(job);
-
- DRM_ERROR("lima job timeout\n");
-
- lima_sched_handle_error_task(pipe, task);
-}
-
static void lima_sched_free_job(struct drm_sched_job *job)
{
struct lima_sched_task *task = to_lima_task(job);
@@ -318,15 +312,6 @@ static const struct drm_sched_backend_ops lima_sched_ops = {
.free_job = lima_sched_free_job,
};
-static void lima_sched_error_work(struct work_struct *work)
-{
- struct lima_sched_pipe *pipe =
- container_of(work, struct lima_sched_pipe, error_work);
- struct lima_sched_task *task = pipe->current_task;
-
- lima_sched_handle_error_task(pipe, task);
-}
-
int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
{
unsigned int timeout = lima_sched_timeout_ms > 0 ?
@@ -335,8 +320,6 @@ int lima_sched_pipe_init(struct lima_sched_pipe *pipe, const char *name)
pipe->fence_context = dma_fence_context_alloc(1);
spin_lock_init(&pipe->fence_lock);
- INIT_WORK(&pipe->error_work, lima_sched_error_work);
-
return drm_sched_init(&pipe->base, &lima_sched_ops, 1, 0,
msecs_to_jiffies(timeout), name);
}
@@ -349,7 +332,7 @@ void lima_sched_pipe_fini(struct lima_sched_pipe *pipe)
void lima_sched_pipe_task_done(struct lima_sched_pipe *pipe)
{
if (pipe->error)
- schedule_work(&pipe->error_work);
+ drm_sched_fault(&pipe->base);
else {
struct lima_sched_task *task = pipe->current_task;
diff --git a/drivers/gpu/drm/lima/lima_sched.h b/drivers/gpu/drm/lima/lima_sched.h
index 928af91c1118..1d814fecbcc0 100644
--- a/drivers/gpu/drm/lima/lima_sched.h
+++ b/drivers/gpu/drm/lima/lima_sched.h
@@ -68,8 +68,6 @@ struct lima_sched_pipe {
void (*task_fini)(struct lima_sched_pipe *pipe);
void (*task_error)(struct lima_sched_pipe *pipe);
void (*task_mmu_error)(struct lima_sched_pipe *pipe);
-
- struct work_struct error_work;
};
int lima_sched_task_init(struct lima_sched_task *task,
diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h
index f9a0c8e9d4d0..04fdf3826643 100644
--- a/drivers/gpu/drm/meson/meson_drv.h
+++ b/drivers/gpu/drm/meson/meson_drv.h
@@ -135,7 +135,7 @@ struct meson_drm {
} venc;
struct {
- dma_addr_t addr_phys;
+ dma_addr_t addr_dma;
uint32_t *addr;
unsigned int offset;
} rdma;
diff --git a/drivers/gpu/drm/meson/meson_rdma.c b/drivers/gpu/drm/meson/meson_rdma.c
index 25b34b1e72a7..130382178c63 100644
--- a/drivers/gpu/drm/meson/meson_rdma.c
+++ b/drivers/gpu/drm/meson/meson_rdma.c
@@ -27,7 +27,7 @@ int meson_rdma_init(struct meson_drm *priv)
/* Allocate a PAGE buffer */
priv->rdma.addr =
dma_alloc_coherent(priv->dev, SZ_4K,
- &priv->rdma.addr_phys,
+ &priv->rdma.addr_dma,
GFP_KERNEL);
if (!priv->rdma.addr)
return -ENOMEM;
@@ -47,16 +47,16 @@ int meson_rdma_init(struct meson_drm *priv)
void meson_rdma_free(struct meson_drm *priv)
{
- if (!priv->rdma.addr && !priv->rdma.addr_phys)
+ if (!priv->rdma.addr && !priv->rdma.addr_dma)
return;
meson_rdma_stop(priv);
dma_free_coherent(priv->dev, SZ_4K,
- priv->rdma.addr, priv->rdma.addr_phys);
+ priv->rdma.addr, priv->rdma.addr_dma);
priv->rdma.addr = NULL;
- priv->rdma.addr_phys = (dma_addr_t)NULL;
+ priv->rdma.addr_dma = (dma_addr_t)0;
}
void meson_rdma_setup(struct meson_drm *priv)
@@ -118,11 +118,11 @@ void meson_rdma_flush(struct meson_drm *priv)
meson_rdma_stop(priv);
/* Start of Channel 1 register writes buffer */
- writel(priv->rdma.addr_phys,
+ writel(priv->rdma.addr_dma,
priv->io_base + _REG(RDMA_AHB_START_ADDR_1));
/* Last byte on Channel 1 register writes buffer */
- writel(priv->rdma.addr_phys + (priv->rdma.offset * RDMA_DESC_SIZE) - 1,
+ writel(priv->rdma.addr_dma + (priv->rdma.offset * RDMA_DESC_SIZE) - 1,
priv->io_base + _REG(RDMA_AHB_END_ADDR_1));
/* Trigger Channel 1 on VSYNC event */
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index 413dbdd1771e..dbb90f2d2ccd 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -393,8 +393,7 @@ static void dispc_get_reg_field(struct dispc_device *dispc,
enum dispc_feat_reg_field id,
u8 *start, u8 *end)
{
- if (id >= dispc->feat->num_reg_fields)
- BUG();
+ BUG_ON(id >= dispc->feat->num_reg_fields);
*start = dispc->feat->reg_fields[id].start;
*end = dispc->feat->reg_fields[id].end;
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index 41f796b28dd5..ae44ac2ec106 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -338,6 +338,17 @@ config DRM_PANEL_SITRONIX_ST7789V
Say Y here if you want to enable support for the Sitronix
ST7789V controller for 240x320 LCD panels
+config DRM_PANEL_SONY_ACX424AKP
+ tristate "Sony ACX424AKP DSI command mode panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ select VIDEOMODE_HELPERS
+ help
+ Say Y here if you want to enable the Sony ACX424 display
+ panel. This panel supports DSI in both command and video
+ mode.
+
config DRM_PANEL_SONY_ACX565AKM
tristate "Sony ACX565AKM panel"
depends on GPIOLIB && OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 4dc7acff21b9..7c4d3c581fd4 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_DRM_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_DRM_PANEL_SHARP_LS043T1LE01) += panel-sharp-ls043t1le01.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7701) += panel-sitronix-st7701.o
obj-$(CONFIG_DRM_PANEL_SITRONIX_ST7789V) += panel-sitronix-st7789v.o
+obj-$(CONFIG_DRM_PANEL_SONY_ACX424AKP) += panel-sony-acx424akp.o
obj-$(CONFIG_DRM_PANEL_SONY_ACX565AKM) += panel-sony-acx565akm.o
obj-$(CONFIG_DRM_PANEL_TPO_TD028TTEC1) += panel-tpo-td028ttec1.o
obj-$(CONFIG_DRM_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index ba3f85f36c2f..e14c14ac62b5 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -629,6 +629,35 @@ static const struct panel_desc auo_b101xtn01 = {
},
};
+static const struct drm_display_mode auo_b116xak01_mode = {
+ .clock = 69300,
+ .hdisplay = 1366,
+ .hsync_start = 1366 + 48,
+ .hsync_end = 1366 + 48 + 32,
+ .htotal = 1366 + 48 + 32 + 10,
+ .vdisplay = 768,
+ .vsync_start = 768 + 4,
+ .vsync_end = 768 + 4 + 6,
+ .vtotal = 768 + 4 + 6 + 15,
+ .vrefresh = 60,
+ .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
+};
+
+static const struct panel_desc auo_b116xak01 = {
+ .modes = &auo_b116xak01_mode,
+ .num_modes = 1,
+ .bpc = 6,
+ .size = {
+ .width = 256,
+ .height = 144,
+ },
+ .delay = {
+ .hpd_absent_delay = 200,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
+ .connector_type = DRM_MODE_CONNECTOR_eDP,
+};
+
static const struct drm_display_mode auo_b116xw03_mode = {
.clock = 70589,
.hdisplay = 1366,
@@ -1008,6 +1037,38 @@ static const struct panel_desc boe_nv101wxmn51 = {
},
};
+static const struct drm_display_mode boe_nv140fhmn49_modes[] = {
+ {
+ .clock = 148500,
+ .hdisplay = 1920,
+ .hsync_start = 1920 + 48,
+ .hsync_end = 1920 + 48 + 32,
+ .htotal = 2200,
+ .vdisplay = 1080,
+ .vsync_start = 1080 + 3,
+ .vsync_end = 1080 + 3 + 5,
+ .vtotal = 1125,
+ .vrefresh = 60,
+ },
+};
+
+static const struct panel_desc boe_nv140fhmn49 = {
+ .modes = boe_nv140fhmn49_modes,
+ .num_modes = ARRAY_SIZE(boe_nv140fhmn49_modes),
+ .bpc = 6,
+ .size = {
+ .width = 309,
+ .height = 174,
+ },
+ .delay = {
+ .prepare = 210,
+ .enable = 50,
+ .unprepare = 160,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB666_1X18,
+ .connector_type = DRM_MODE_CONNECTOR_eDP,
+};
+
static const struct drm_display_mode cdtech_s043wq26h_ct7_mode = {
.clock = 9000,
.hdisplay = 480,
@@ -2553,6 +2614,30 @@ static const struct panel_desc samsung_ltn140at29_301 = {
},
};
+static const struct display_timing satoz_sat050at40h12r2_timing = {
+ .pixelclock = {33300000, 33300000, 50000000},
+ .hactive = {800, 800, 800},
+ .hfront_porch = {16, 210, 354},
+ .hback_porch = {46, 46, 46},
+ .hsync_len = {1, 1, 40},
+ .vactive = {480, 480, 480},
+ .vfront_porch = {7, 22, 147},
+ .vback_porch = {23, 23, 23},
+ .vsync_len = {1, 1, 20},
+};
+
+static const struct panel_desc satoz_sat050at40h12r2 = {
+ .timings = &satoz_sat050at40h12r2_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 108,
+ .height = 65,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+ .connector_type = DRM_MODE_CONNECTOR_LVDS,
+};
+
static const struct drm_display_mode sharp_ld_d5116z01b_mode = {
.clock = 168480,
.hdisplay = 1920,
@@ -3126,6 +3211,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "auo,b101xtn01",
.data = &auo_b101xtn01,
}, {
+ .compatible = "auo,b116xa01",
+ .data = &auo_b116xak01,
+ }, {
.compatible = "auo,b116xw03",
.data = &auo_b116xw03,
}, {
@@ -3168,6 +3256,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "boe,nv101wxmn51",
.data = &boe_nv101wxmn51,
}, {
+ .compatible = "boe,nv140fhmn49",
+ .data = &boe_nv140fhmn49,
+ }, {
.compatible = "cdtech,s043wq26h-ct7",
.data = &cdtech_s043wq26h_ct7,
}, {
@@ -3357,6 +3448,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "samsung,ltn140at29-301",
.data = &samsung_ltn140at29_301,
}, {
+ .compatible = "satoz,sat050at40h12r2",
+ .data = &satoz_sat050at40h12r2,
+ }, {
.compatible = "sharp,ld-d5116z01b",
.data = &sharp_ld_d5116z01b,
}, {
diff --git a/drivers/gpu/drm/panel/panel-sony-acx424akp.c b/drivers/gpu/drm/panel/panel-sony-acx424akp.c
new file mode 100644
index 000000000000..de0abf76ae6f
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-sony-acx424akp.c
@@ -0,0 +1,550 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * MIPI-DSI Sony ACX424AKP panel driver. This is a 480x864
+ * AMOLED panel with a command-only DSI interface.
+ *
+ * Copyright (C) Linaro Ltd. 2019
+ * Author: Linus Walleij
+ * Based on code and know-how from Marcus Lorentzon
+ * Copyright (C) ST-Ericsson SA 2010
+ */
+#include <linux/backlight.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#define ACX424_DCS_READ_ID1 0xDA
+#define ACX424_DCS_READ_ID2 0xDB
+#define ACX424_DCS_READ_ID3 0xDC
+#define ACX424_DCS_SET_MDDI 0xAE
+
+/*
+ * Sony seems to use vendor ID 0x81
+ */
+#define DISPLAY_SONY_ACX424AKP_ID1 0x811b
+#define DISPLAY_SONY_ACX424AKP_ID2 0x811a
+/*
+ * The third ID looks like a bug, vendor IDs begin at 0x80
+ * and panel 00 ... seems like default values.
+ */
+#define DISPLAY_SONY_ACX424AKP_ID3 0x8000
+
+struct acx424akp {
+ struct drm_panel panel;
+ struct device *dev;
+ struct backlight_device *bl;
+ struct regulator *supply;
+ struct gpio_desc *reset_gpio;
+ bool video_mode;
+};
+
+static const struct drm_display_mode sony_acx424akp_vid_mode = {
+ .clock = 330000,
+ .hdisplay = 480,
+ .hsync_start = 480 + 15,
+ .hsync_end = 480 + 15 + 0,
+ .htotal = 480 + 15 + 0 + 15,
+ .vdisplay = 864,
+ .vsync_start = 864 + 14,
+ .vsync_end = 864 + 14 + 1,
+ .vtotal = 864 + 14 + 1 + 11,
+ .vrefresh = 60,
+ .width_mm = 48,
+ .height_mm = 84,
+ .flags = DRM_MODE_FLAG_PVSYNC,
+};
+
+/*
+ * The timings are not very helpful as the display is used in
+ * command mode using the maximum HS frequency.
+ */
+static const struct drm_display_mode sony_acx424akp_cmd_mode = {
+ .clock = 420160,
+ .hdisplay = 480,
+ .hsync_start = 480 + 154,
+ .hsync_end = 480 + 154 + 16,
+ .htotal = 480 + 154 + 16 + 32,
+ .vdisplay = 864,
+ .vsync_start = 864 + 1,
+ .vsync_end = 864 + 1 + 1,
+ .vtotal = 864 + 1 + 1 + 1,
+ /*
+ * Some desired refresh rate, experiments at the maximum "pixel"
+ * clock speed (HS clock 420 MHz) yields around 117Hz.
+ */
+ .vrefresh = 60,
+ .width_mm = 48,
+ .height_mm = 84,
+};
+
+static inline struct acx424akp *panel_to_acx424akp(struct drm_panel *panel)
+{
+ return container_of(panel, struct acx424akp, panel);
+}
+
+#define FOSC 20 /* 20Mhz */
+#define SCALE_FACTOR_NS_DIV_MHZ 1000
+
+static int acx424akp_set_brightness(struct backlight_device *bl)
+{
+ struct acx424akp *acx = bl_get_data(bl);
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
+ int period_ns = 1023;
+ int duty_ns = bl->props.brightness;
+ u8 pwm_ratio;
+ u8 pwm_div;
+ u8 par;
+ int ret;
+
+ /* Calculate the PWM duty cycle in n/256's */
+ pwm_ratio = max(((duty_ns * 256) / period_ns) - 1, 1);
+ pwm_div = max(1,
+ ((FOSC * period_ns) / 256) /
+ SCALE_FACTOR_NS_DIV_MHZ);
+
+ /* Set up PWM dutycycle ONE byte (differs from the standard) */
+ DRM_DEV_DEBUG(acx->dev, "calculated duty cycle %02x\n", pwm_ratio);
+ ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
+ &pwm_ratio, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev,
+ "failed to set display PWM ratio (%d)\n",
+ ret);
+ return ret;
+ }
+
+ /*
+ * Sequence to write PWMDIV:
+ * address data
+ * 0xF3 0xAA CMD2 Unlock
+ * 0x00 0x01 Enter CMD2 page 0
+ * 0X7D 0x01 No reload MTP of CMD2 P1
+ * 0x22 PWMDIV
+ * 0x7F 0xAA CMD2 page 1 lock
+ */
+ par = 0xaa;
+ ret = mipi_dsi_dcs_write(dsi, 0xf3, &par, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev,
+ "failed to unlock CMD 2 (%d)\n",
+ ret);
+ return ret;
+ }
+ par = 0x01;
+ ret = mipi_dsi_dcs_write(dsi, 0x00, &par, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev,
+ "failed to enter page 1 (%d)\n",
+ ret);
+ return ret;
+ }
+ par = 0x01;
+ ret = mipi_dsi_dcs_write(dsi, 0x7d, &par, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev,
+ "failed to disable MTP reload (%d)\n",
+ ret);
+ return ret;
+ }
+ ret = mipi_dsi_dcs_write(dsi, 0x22, &pwm_div, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev,
+ "failed to set PWM divisor (%d)\n",
+ ret);
+ return ret;
+ }
+ par = 0xaa;
+ ret = mipi_dsi_dcs_write(dsi, 0x7f, &par, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev,
+ "failed to lock CMD 2 (%d)\n",
+ ret);
+ return ret;
+ }
+
+ /* Enable backlight */
+ par = 0x24;
+ ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
+ &par, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev,
+ "failed to enable display backlight (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct backlight_ops acx424akp_bl_ops = {
+ .update_status = acx424akp_set_brightness,
+};
+
+static int acx424akp_read_id(struct acx424akp *acx)
+{
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
+ u8 vendor, version, panel;
+ u16 val;
+ int ret;
+
+ ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID1, &vendor, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev, "could not vendor ID byte\n");
+ return ret;
+ }
+ ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID2, &version, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev, "could not read device version byte\n");
+ return ret;
+ }
+ ret = mipi_dsi_dcs_read(dsi, ACX424_DCS_READ_ID3, &panel, 1);
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev, "could not read panel ID byte\n");
+ return ret;
+ }
+
+ if (vendor == 0x00) {
+ DRM_DEV_ERROR(acx->dev, "device vendor ID is zero\n");
+ return -ENODEV;
+ }
+
+ val = (vendor << 8) | panel;
+ switch (val) {
+ case DISPLAY_SONY_ACX424AKP_ID1:
+ case DISPLAY_SONY_ACX424AKP_ID2:
+ case DISPLAY_SONY_ACX424AKP_ID3:
+ DRM_DEV_INFO(acx->dev,
+ "MTP vendor: %02x, version: %02x, panel: %02x\n",
+ vendor, version, panel);
+ break;
+ default:
+ DRM_DEV_INFO(acx->dev,
+ "unknown vendor: %02x, version: %02x, panel: %02x\n",
+ vendor, version, panel);
+ break;
+ }
+
+ return 0;
+}
+
+static int acx424akp_power_on(struct acx424akp *acx)
+{
+ int ret;
+
+ ret = regulator_enable(acx->supply);
+ if (ret) {
+ DRM_DEV_ERROR(acx->dev, "failed to enable supply (%d)\n", ret);
+ return ret;
+ }
+
+ /* Assert RESET */
+ gpiod_set_value_cansleep(acx->reset_gpio, 1);
+ udelay(20);
+ /* De-assert RESET */
+ gpiod_set_value_cansleep(acx->reset_gpio, 0);
+ usleep_range(11000, 20000);
+
+ return 0;
+}
+
+static void acx424akp_power_off(struct acx424akp *acx)
+{
+ /* Assert RESET */
+ gpiod_set_value_cansleep(acx->reset_gpio, 1);
+ usleep_range(11000, 20000);
+
+ regulator_disable(acx->supply);
+}
+
+static int acx424akp_prepare(struct drm_panel *panel)
+{
+ struct acx424akp *acx = panel_to_acx424akp(panel);
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
+ const u8 mddi = 3;
+ int ret;
+
+ ret = acx424akp_power_on(acx);
+ if (ret)
+ return ret;
+
+ ret = acx424akp_read_id(acx);
+ if (ret) {
+ DRM_DEV_ERROR(acx->dev, "failed to read panel ID (%d)\n", ret);
+ goto err_power_off;
+ }
+
+ /* Enabe tearing mode: send TE (tearing effect) at VBLANK */
+ ret = mipi_dsi_dcs_set_tear_on(dsi,
+ MIPI_DSI_DCS_TEAR_MODE_VBLANK);
+ if (ret) {
+ DRM_DEV_ERROR(acx->dev, "failed to enable vblank TE (%d)\n",
+ ret);
+ goto err_power_off;
+ }
+
+ /*
+ * Set MDDI
+ *
+ * This presumably deactivates the Qualcomm MDDI interface and
+ * selects DSI, similar code is found in other drivers such as the
+ * Sharp LS043T1LE01 which makes us suspect that this panel may be
+ * using a Novatek NT35565 or similar display driver chip that shares
+ * this command. Due to the lack of documentation we cannot know for
+ * sure.
+ */
+ ret = mipi_dsi_dcs_write(dsi, ACX424_DCS_SET_MDDI,
+ &mddi, sizeof(mddi));
+ if (ret < 0) {
+ DRM_DEV_ERROR(acx->dev, "failed to set MDDI (%d)\n", ret);
+ goto err_power_off;
+ }
+
+ /* Exit sleep mode */
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret) {
+ DRM_DEV_ERROR(acx->dev, "failed to exit sleep mode (%d)\n",
+ ret);
+ goto err_power_off;
+ }
+ msleep(140);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret) {
+ DRM_DEV_ERROR(acx->dev, "failed to turn display on (%d)\n",
+ ret);
+ goto err_power_off;
+ }
+ if (acx->video_mode) {
+ /* In video mode turn peripheral on */
+ ret = mipi_dsi_turn_on_peripheral(dsi);
+ if (ret) {
+ dev_err(acx->dev, "failed to turn on peripheral\n");
+ goto err_power_off;
+ }
+ }
+
+ acx->bl->props.power = FB_BLANK_NORMAL;
+
+ return 0;
+
+err_power_off:
+ acx424akp_power_off(acx);
+ return ret;
+}
+
+static int acx424akp_unprepare(struct drm_panel *panel)
+{
+ struct acx424akp *acx = panel_to_acx424akp(panel);
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(acx->dev);
+ u8 par;
+ int ret;
+
+ /* Disable backlight */
+ par = 0x00;
+ ret = mipi_dsi_dcs_write(dsi, MIPI_DCS_WRITE_CONTROL_DISPLAY,
+ &par, 1);
+ if (ret) {
+ DRM_DEV_ERROR(acx->dev,
+ "failed to disable display backlight (%d)\n",
+ ret);
+ return ret;
+ }
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret) {
+ DRM_DEV_ERROR(acx->dev, "failed to turn display off (%d)\n",
+ ret);
+ return ret;
+ }
+
+ /* Enter sleep mode */
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret) {
+ DRM_DEV_ERROR(acx->dev, "failed to enter sleep mode (%d)\n",
+ ret);
+ return ret;
+ }
+ msleep(85);
+
+ acx424akp_power_off(acx);
+ acx->bl->props.power = FB_BLANK_POWERDOWN;
+
+ return 0;
+}
+
+static int acx424akp_enable(struct drm_panel *panel)
+{
+ struct acx424akp *acx = panel_to_acx424akp(panel);
+
+ /*
+ * The backlight is on as long as the display is on
+ * so no use to call backlight_enable() here.
+ */
+ acx->bl->props.power = FB_BLANK_UNBLANK;
+
+ return 0;
+}
+
+static int acx424akp_disable(struct drm_panel *panel)
+{
+ struct acx424akp *acx = panel_to_acx424akp(panel);
+
+ /*
+ * The backlight is on as long as the display is on
+ * so no use to call backlight_disable() here.
+ */
+ acx->bl->props.power = FB_BLANK_NORMAL;
+
+ return 0;
+}
+
+static int acx424akp_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct acx424akp *acx = panel_to_acx424akp(panel);
+ struct drm_display_mode *mode;
+
+ if (acx->video_mode)
+ mode = drm_mode_duplicate(connector->dev,
+ &sony_acx424akp_vid_mode);
+ else
+ mode = drm_mode_duplicate(connector->dev,
+ &sony_acx424akp_cmd_mode);
+ if (!mode) {
+ DRM_ERROR("bad mode or failed to add mode\n");
+ return -EINVAL;
+ }
+ drm_mode_set_name(mode);
+ mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
+
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+
+ drm_mode_probed_add(connector, mode);
+
+ return 1; /* Number of modes */
+}
+
+static const struct drm_panel_funcs acx424akp_drm_funcs = {
+ .disable = acx424akp_disable,
+ .unprepare = acx424akp_unprepare,
+ .prepare = acx424akp_prepare,
+ .enable = acx424akp_enable,
+ .get_modes = acx424akp_get_modes,
+};
+
+static int acx424akp_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct acx424akp *acx;
+ int ret;
+
+ acx = devm_kzalloc(dev, sizeof(struct acx424akp), GFP_KERNEL);
+ if (!acx)
+ return -ENOMEM;
+ acx->video_mode = of_property_read_bool(dev->of_node,
+ "enforce-video-mode");
+
+ mipi_dsi_set_drvdata(dsi, acx);
+ acx->dev = dev;
+
+ dsi->lanes = 2;
+ dsi->format = MIPI_DSI_FMT_RGB888;
+ /*
+ * FIXME: these come from the ST-Ericsson vendor driver for the
+ * HREF520 and seems to reflect limitations in the PLLs on that
+ * platform, if you have the datasheet, please cross-check the
+ * actual max rates.
+ */
+ dsi->lp_rate = 19200000;
+ dsi->hs_rate = 420160000;
+
+ if (acx->video_mode)
+ /* Burst mode using event for sync */
+ dsi->mode_flags =
+ MIPI_DSI_MODE_VIDEO |
+ MIPI_DSI_MODE_VIDEO_BURST;
+ else
+ dsi->mode_flags =
+ MIPI_DSI_CLOCK_NON_CONTINUOUS |
+ MIPI_DSI_MODE_EOT_PACKET;
+
+ acx->supply = devm_regulator_get(dev, "vddi");
+ if (IS_ERR(acx->supply))
+ return PTR_ERR(acx->supply);
+
+ /* This asserts RESET by default */
+ acx->reset_gpio = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(acx->reset_gpio)) {
+ ret = PTR_ERR(acx->reset_gpio);
+ if (ret != -EPROBE_DEFER)
+ DRM_DEV_ERROR(dev, "failed to request GPIO (%d)\n",
+ ret);
+ return ret;
+ }
+
+ drm_panel_init(&acx->panel, dev, &acx424akp_drm_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ acx->bl = devm_backlight_device_register(dev, "acx424akp", dev, acx,
+ &acx424akp_bl_ops, NULL);
+ if (IS_ERR(acx->bl)) {
+ DRM_DEV_ERROR(dev, "failed to register backlight device\n");
+ return PTR_ERR(acx->bl);
+ }
+ acx->bl->props.max_brightness = 1023;
+ acx->bl->props.brightness = 512;
+ acx->bl->props.power = FB_BLANK_POWERDOWN;
+
+ ret = drm_panel_add(&acx->panel);
+ if (ret < 0)
+ return ret;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ drm_panel_remove(&acx->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int acx424akp_remove(struct mipi_dsi_device *dsi)
+{
+ struct acx424akp *acx = mipi_dsi_get_drvdata(dsi);
+
+ mipi_dsi_detach(dsi);
+ drm_panel_remove(&acx->panel);
+
+ return 0;
+}
+
+static const struct of_device_id acx424akp_of_match[] = {
+ { .compatible = "sony,acx424akp" },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, acx424akp_of_match);
+
+static struct mipi_dsi_driver acx424akp_driver = {
+ .probe = acx424akp_probe,
+ .remove = acx424akp_remove,
+ .driver = {
+ .name = "panel-sony-acx424akp",
+ .of_match_table = acx424akp_of_match,
+ },
+};
+module_mipi_dsi_driver(acx424akp_driver);
+
+MODULE_AUTHOR("Linus Wallei <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("MIPI-DSI Sony acx424akp Panel Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c
index 961519ce6634..8ffa4fbbdeb3 100644
--- a/drivers/gpu/drm/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c
@@ -590,9 +590,8 @@ static void __rcar_lvds_atomic_enable(struct drm_bridge *bridge,
}
static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+ struct drm_atomic_state *state)
{
- struct drm_atomic_state *state = old_bridge_state->base.state;
struct drm_connector *connector;
struct drm_crtc *crtc;
@@ -604,7 +603,7 @@ static void rcar_lvds_atomic_enable(struct drm_bridge *bridge,
}
static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
- struct drm_bridge_state *old_bridge_state)
+ struct drm_atomic_state *state)
{
struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge);
@@ -619,8 +618,7 @@ static void rcar_lvds_atomic_disable(struct drm_bridge *bridge,
/* Disable the companion LVDS encoder in dual-link mode. */
if (lvds->link_type != RCAR_LVDS_SINGLE_LINK && lvds->companion)
- lvds->companion->funcs->atomic_disable(lvds->companion,
- old_bridge_state);
+ lvds->companion->funcs->atomic_disable(lvds->companion, state);
clk_disable_unprepare(lvds->clocks.mod);
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 4e29f4fe4a05..072ea113e6be 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -856,6 +856,13 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
ret = PTR_ERR(backend->mod_clk);
goto err_disable_bus_clk;
}
+
+ ret = clk_set_rate_exclusive(backend->mod_clk, 300000000);
+ if (ret) {
+ dev_err(dev, "Couldn't set the module clock frequency\n");
+ goto err_disable_bus_clk;
+ }
+
clk_prepare_enable(backend->mod_clk);
backend->ram_clk = devm_clk_get(dev, "ram");
@@ -932,6 +939,7 @@ static int sun4i_backend_bind(struct device *dev, struct device *master,
err_disable_ram_clk:
clk_disable_unprepare(backend->ram_clk);
err_disable_mod_clk:
+ clk_rate_exclusive_put(backend->mod_clk);
clk_disable_unprepare(backend->mod_clk);
err_disable_bus_clk:
clk_disable_unprepare(backend->bus_clk);
@@ -952,6 +960,7 @@ static void sun4i_backend_unbind(struct device *dev, struct device *master,
sun4i_backend_free_sat(dev);
clk_disable_unprepare(backend->ram_clk);
+ clk_rate_exclusive_put(backend->mod_clk);
clk_disable_unprepare(backend->mod_clk);
clk_disable_unprepare(backend->bus_clk);
reset_control_assert(backend->reset);
diff --git a/drivers/gpu/drm/sun4i/sun6i_drc.c b/drivers/gpu/drm/sun4i/sun6i_drc.c
index f7ab72244796..4fbe9a6b5182 100644
--- a/drivers/gpu/drm/sun4i/sun6i_drc.c
+++ b/drivers/gpu/drm/sun4i/sun6i_drc.c
@@ -56,6 +56,13 @@ static int sun6i_drc_bind(struct device *dev, struct device *master,
ret = PTR_ERR(drc->mod_clk);
goto err_disable_bus_clk;
}
+
+ ret = clk_set_rate_exclusive(drc->mod_clk, 300000000);
+ if (ret) {
+ dev_err(dev, "Couldn't set the module clock frequency\n");
+ goto err_disable_bus_clk;
+ }
+
clk_prepare_enable(drc->mod_clk);
return 0;
@@ -72,6 +79,7 @@ static void sun6i_drc_unbind(struct device *dev, struct device *master,
{
struct sun6i_drc *drc = dev_get_drvdata(dev);
+ clk_rate_exclusive_put(drc->mod_clk);
clk_disable_unprepare(drc->mod_clk);
clk_disable_unprepare(drc->bus_clk);
reset_control_assert(drc->reset);
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 50269ffbcb6b..21a629adcb51 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1430,9 +1430,10 @@ static int tegra_hdmi_init(struct host1x_client *client)
hdmi->output.dev = client->dev;
- drm_connector_init(drm, &hdmi->output.connector,
- &tegra_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_init_with_ddc(drm, &hdmi->output.connector,
+ &tegra_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ hdmi->output.ddc);
drm_connector_helper_add(&hdmi->output.connector,
&tegra_hdmi_connector_helper_funcs);
hdmi->output.connector.dpms = DRM_MODE_DPMS_OFF;
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index a68d3b36b972..1b8087d2dafe 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -3086,9 +3086,10 @@ static int tegra_sor_init(struct host1x_client *client)
sor->output.dev = sor->dev;
- drm_connector_init(drm, &sor->output.connector,
- &tegra_sor_connector_funcs,
- connector);
+ drm_connector_init_with_ddc(drm, &sor->output.connector,
+ &tegra_sor_connector_funcs,
+ connector,
+ sor->output.ddc);
drm_connector_helper_add(&sor->output.connector,
&tegra_sor_connector_helper_funcs);
sor->output.connector.dpms = DRM_MODE_DPMS_OFF;
diff --git a/drivers/gpu/drm/udl/Kconfig b/drivers/gpu/drm/udl/Kconfig
index 065974bf010e..1f497d8f1ae5 100644
--- a/drivers/gpu/drm/udl/Kconfig
+++ b/drivers/gpu/drm/udl/Kconfig
@@ -2,9 +2,8 @@
config DRM_UDL
tristate "DisplayLink"
depends on DRM
- depends on USB_SUPPORT
+ depends on USB
depends on USB_ARCH_HAS_HCD
- select USB
select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
help
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index 6c5b80ad6154..fd8a2eb60505 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -753,10 +753,19 @@ static void vc4_dsi_encoder_disable(struct drm_encoder *encoder)
struct vc4_dsi_encoder *vc4_encoder = to_vc4_dsi_encoder(encoder);
struct vc4_dsi *dsi = vc4_encoder->dsi;
struct device *dev = &dsi->pdev->dev;
+ struct drm_bridge *iter;
+
+ list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
+ if (iter->funcs->disable)
+ iter->funcs->disable(iter);
+ }
- drm_bridge_chain_disable(dsi->bridge);
vc4_dsi_ulps(dsi, true);
- drm_bridge_chain_post_disable(dsi->bridge);
+
+ list_for_each_entry_from(iter, &dsi->bridge_chain, chain_node) {
+ if (iter->funcs->post_disable)
+ iter->funcs->post_disable(iter);
+ }
clk_disable_unprepare(dsi->pll_phy_clock);
clk_disable_unprepare(dsi->escape_clock);
@@ -824,6 +833,7 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
struct vc4_dsi *dsi = vc4_encoder->dsi;
struct device *dev = &dsi->pdev->dev;
bool debug_dump_regs = false;
+ struct drm_bridge *iter;
unsigned long hs_clock;
u32 ui_ns;
/* Minimum LP state duration in escape clock cycles. */
@@ -1056,7 +1066,10 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
vc4_dsi_ulps(dsi, false);
- drm_bridge_chain_pre_enable(dsi->bridge);
+ list_for_each_entry_reverse(iter, &dsi->bridge_chain, chain_node) {
+ if (iter->funcs->pre_enable)
+ iter->funcs->pre_enable(iter);
+ }
if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
DSI_PORT_WRITE(DISP0_CTRL,
@@ -1073,7 +1086,10 @@ static void vc4_dsi_encoder_enable(struct drm_encoder *encoder)
DSI_DISP0_ENABLE);
}
- drm_bridge_chain_enable(dsi->bridge);
+ list_for_each_entry(iter, &dsi->bridge_chain, chain_node) {
+ if (iter->funcs->enable)
+ iter->funcs->enable(iter);
+ }
if (debug_dump_regs) {
struct drm_printer p = drm_info_printer(&dsi->pdev->dev);
@@ -1613,7 +1629,7 @@ static int vc4_dsi_bind(struct device *dev, struct device *master, void *data)
* from our driver, since we need to sequence them within the
* encoder's enable/disable paths.
*/
- list_splice(&dsi->encoder->bridge_chain, &dsi->bridge_chain);
+ list_splice_init(&dsi->encoder->bridge_chain, &dsi->bridge_chain);
if (dsi->port == 0)
vc4_debugfs_add_regset32(drm, "dsi0_regs", &dsi->regset);
@@ -1639,7 +1655,7 @@ static void vc4_dsi_unbind(struct device *dev, struct device *master,
* Restore the bridge_chain so the bridge detach procedure can happen
* normally.
*/
- list_splice(&dsi->bridge_chain, &dsi->encoder->bridge_chain);
+ list_splice_init(&dsi->bridge_chain, &dsi->encoder->bridge_chain);
vc4_dsi_encoder_destroy(dsi->encoder);
if (dsi->port == 1)
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 1c62c6c9244b..cea18dc15f77 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -267,7 +267,8 @@ static const struct drm_connector_helper_funcs vc4_hdmi_connector_helper_funcs =
};
static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
- struct drm_encoder *encoder)
+ struct drm_encoder *encoder,
+ struct i2c_adapter *ddc)
{
struct drm_connector *connector;
struct vc4_hdmi_connector *hdmi_connector;
@@ -281,8 +282,10 @@ static struct drm_connector *vc4_hdmi_connector_init(struct drm_device *dev,
hdmi_connector->encoder = encoder;
- drm_connector_init(dev, connector, &vc4_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_init_with_ddc(dev, connector,
+ &vc4_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ ddc);
drm_connector_helper_add(connector, &vc4_hdmi_connector_helper_funcs);
/* Create and attach TV margin props to this connector. */
@@ -1395,7 +1398,8 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
DRM_MODE_ENCODER_TMDS, NULL);
drm_encoder_helper_add(hdmi->encoder, &vc4_hdmi_encoder_helper_funcs);
- hdmi->connector = vc4_hdmi_connector_init(drm, hdmi->encoder);
+ hdmi->connector =
+ vc4_hdmi_connector_init(drm, hdmi->encoder, hdmi->ddc);
if (IS_ERR(hdmi->connector)) {
ret = PTR_ERR(hdmi->connector);
goto err_destroy_encoder;
diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c
index a50f5a1f09b8..b98a1420dcd3 100644
--- a/drivers/gpu/drm/zte/zx_hdmi.c
+++ b/drivers/gpu/drm/zte/zx_hdmi.c
@@ -319,8 +319,10 @@ static int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi)
hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
- drm_connector_init(drm, &hdmi->connector, &zx_hdmi_connector_funcs,
- DRM_MODE_CONNECTOR_HDMIA);
+ drm_connector_init_with_ddc(drm, &hdmi->connector,
+ &zx_hdmi_connector_funcs,
+ DRM_MODE_CONNECTOR_HDMIA,
+ &hdmi->ddc->adap);
drm_connector_helper_add(&hdmi->connector,
&zx_hdmi_connector_helper_funcs);
diff --git a/drivers/gpu/drm/zte/zx_vga.c b/drivers/gpu/drm/zte/zx_vga.c
index 9b67e419280c..c4fa3bbaba78 100644
--- a/drivers/gpu/drm/zte/zx_vga.c
+++ b/drivers/gpu/drm/zte/zx_vga.c
@@ -165,8 +165,10 @@ static int zx_vga_register(struct drm_device *drm, struct zx_vga *vga)
vga->connector.polled = DRM_CONNECTOR_POLL_HPD;
- ret = drm_connector_init(drm, connector, &zx_vga_connector_funcs,
- DRM_MODE_CONNECTOR_VGA);
+ ret = drm_connector_init_with_ddc(drm, connector,
+ &zx_vga_connector_funcs,
+ DRM_MODE_CONNECTOR_VGA,
+ &vga->ddc->adap);
if (ret) {
DRM_DEV_ERROR(dev, "failed to init connector: %d\n", ret);
goto clean_encoder;