Commit 9a5c1586 authored by Dmitry Baryshkov's avatar Dmitry Baryshkov

Merge remote-tracking branch 'msm/msm-fixes' into HEAD

parents 7f7a942c e0e86f25
......@@ -155,7 +155,7 @@ config DRM_MSM_HDMI
Compile in support for the HDMI output MSM DRM driver. It can
be a primary or a secondary display on device. Note that this is used
only for the direct HDMI output. If the device outputs HDMI data
throught some kind of DSI-to-HDMI bridge, this option can be disabled.
through some kind of DSI-to-HDMI bridge, this option can be disabled.
config DRM_MSM_HDMI_HDCP
bool "Enable HDMI HDCP support in MSM DRM driver"
......
......@@ -91,7 +91,7 @@ struct a6xx_state_memobj {
static void *state_kcalloc(struct a6xx_gpu_state *a6xx_state, int nr, size_t objsize)
{
struct a6xx_state_memobj *obj =
kzalloc((nr * objsize) + sizeof(*obj), GFP_KERNEL);
kvzalloc((nr * objsize) + sizeof(*obj), GFP_KERNEL);
if (!obj)
return NULL;
......@@ -813,6 +813,9 @@ static struct msm_gpu_state_bo *a6xx_snapshot_gmu_bo(
{
struct msm_gpu_state_bo *snapshot;
if (!bo->size)
return NULL;
snapshot = state_kcalloc(a6xx_state, 1, sizeof(*snapshot));
if (!snapshot)
return NULL;
......@@ -1040,8 +1043,13 @@ static void a6xx_gpu_state_destroy(struct kref *kref)
if (a6xx_state->gmu_hfi)
kvfree(a6xx_state->gmu_hfi->data);
list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node)
kfree(obj);
if (a6xx_state->gmu_debug)
kvfree(a6xx_state->gmu_debug->data);
list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node) {
list_del(&obj->node);
kvfree(obj);
}
adreno_gpu_state_destroy(state);
kfree(a6xx_state);
......
......@@ -679,6 +679,9 @@ static int adreno_system_suspend(struct device *dev)
struct msm_gpu *gpu = dev_to_gpu(dev);
int remaining, ret;
if (!gpu)
return 0;
suspend_scheduler(gpu);
remaining = wait_event_timeout(gpu->retire_event,
......@@ -700,7 +703,12 @@ static int adreno_system_suspend(struct device *dev)
static int adreno_system_resume(struct device *dev)
{
resume_scheduler(dev_to_gpu(dev));
struct msm_gpu *gpu = dev_to_gpu(dev);
if (!gpu)
return 0;
resume_scheduler(gpu);
return pm_runtime_force_resume(dev);
}
......
......@@ -729,7 +729,12 @@ static char *adreno_gpu_ascii85_encode(u32 *src, size_t len)
return buf;
}
/* len is expected to be in bytes */
/* len is expected to be in bytes
*
* WARNING: *ptr should be allocated with kvmalloc or friends. It can be free'd
* with kvfree() and replaced with a newly kvmalloc'd buffer on the first call
* when the unencoded raw data is encoded
*/
void adreno_show_object(struct drm_printer *p, void **ptr, int len,
bool *encoded)
{
......
......@@ -56,8 +56,9 @@ static int mdp4_lvds_connector_get_modes(struct drm_connector *connector)
return ret;
}
static int mdp4_lvds_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
static enum drm_mode_status
mdp4_lvds_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
struct mdp4_lvds_connector *mdp4_lvds_connector =
to_mdp4_lvds_connector(connector);
......
......@@ -1243,8 +1243,7 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
{
int ret = 0;
const u8 *dpcd = ctrl->panel->dpcd;
u8 encoding = DP_SET_ANSI_8B10B;
u8 ssc;
u8 encoding[] = { 0, DP_SET_ANSI_8B10B };
u8 assr;
struct dp_link_info link_info = {0};
......@@ -1256,13 +1255,11 @@ static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl,
dp_aux_link_configure(ctrl->aux, &link_info);
if (drm_dp_max_downspread(dpcd)) {
ssc = DP_SPREAD_AMP_0_5;
drm_dp_dpcd_write(ctrl->aux, DP_DOWNSPREAD_CTRL, &ssc, 1);
}
if (drm_dp_max_downspread(dpcd))
encoding[0] |= DP_SPREAD_AMP_0_5;
drm_dp_dpcd_write(ctrl->aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
&encoding, 1);
/* config DOWNSPREAD_CTRL and MAIN_LINK_CHANNEL_CODING_SET */
drm_dp_dpcd_write(ctrl->aux, DP_DOWNSPREAD_CTRL, encoding, 2);
if (drm_dp_alternate_scrambler_reset_cap(dpcd)) {
assr = DP_ALTERNATE_SCRAMBLER_RESET_ENABLE;
......
......@@ -1249,7 +1249,7 @@ int dp_display_request_irq(struct msm_dp *dp_display)
return -EINVAL;
}
rc = devm_request_irq(&dp->pdev->dev, dp->irq,
rc = devm_request_irq(dp_display->drm_dev->dev, dp->irq,
dp_display_irq_handler,
IRQF_TRIGGER_HIGH, "dp_display_isr", dp);
if (rc < 0) {
......@@ -1528,6 +1528,11 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor)
}
}
static void of_dp_aux_depopulate_bus_void(void *data)
{
of_dp_aux_depopulate_bus(data);
}
static int dp_display_get_next_bridge(struct msm_dp *dp)
{
int rc;
......@@ -1552,10 +1557,16 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
* panel driver is probed asynchronously but is the best we
* can do without a bigger driver reorganization.
*/
rc = devm_of_dp_aux_populate_ep_devices(dp_priv->aux);
rc = of_dp_aux_populate_bus(dp_priv->aux, NULL);
of_node_put(aux_bus);
if (rc)
goto error;
rc = devm_add_action_or_reset(dp->drm_dev->dev,
of_dp_aux_depopulate_bus_void,
dp_priv->aux);
if (rc)
goto error;
} else if (dp->is_edp) {
DRM_ERROR("eDP aux_bus not found\n");
return -ENODEV;
......@@ -1568,7 +1579,7 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
* For DisplayPort interfaces external bridges are optional, so
* silently ignore an error if one is not present (-ENODEV).
*/
rc = dp_parser_find_next_bridge(dp_priv->parser);
rc = devm_dp_parser_find_next_bridge(dp->drm_dev->dev, dp_priv->parser);
if (!dp->is_edp && rc == -ENODEV)
return 0;
......@@ -1597,6 +1608,12 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
return -EINVAL;
priv = dev->dev_private;
if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) {
DRM_DEV_ERROR(dev->dev, "too many bridges\n");
return -ENOSPC;
}
dp_display->drm_dev = dev;
dp_priv = container_of(dp_display, struct dp_display_private, dp_display);
......
......@@ -31,6 +31,36 @@ static enum drm_connector_status dp_bridge_detect(struct drm_bridge *bridge)
connector_status_disconnected;
}
static int dp_bridge_atomic_check(struct drm_bridge *bridge,
struct drm_bridge_state *bridge_state,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
struct msm_dp *dp;
dp = to_dp_bridge(bridge)->dp_display;
drm_dbg_dp(dp->drm_dev, "is_connected = %s\n",
(dp->is_connected) ? "true" : "false");
/*
* There is no protection in the DRM framework to check if the display
* pipeline has been already disabled before trying to disable it again.
* Hence if the sink is unplugged, the pipeline gets disabled, but the
* crtc->active is still true. Any attempt to set the mode or manually
* disable this encoder will result in the crash.
*
* TODO: add support for telling the DRM subsystem that the pipeline is
* disabled by the hardware and thus all access to it should be forbidden.
* After that this piece of code can be removed.
*/
if (bridge->ops & DRM_BRIDGE_OP_HPD)
return (dp->is_connected) ? 0 : -ENOTCONN;
return 0;
}
/**
* dp_bridge_get_modes - callback to add drm modes via drm_mode_probed_add()
* @bridge: Poiner to drm bridge
......@@ -61,6 +91,9 @@ static int dp_bridge_get_modes(struct drm_bridge *bridge, struct drm_connector *
}
static const struct drm_bridge_funcs dp_bridge_ops = {
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_reset = drm_atomic_helper_bridge_reset,
.enable = dp_bridge_enable,
.disable = dp_bridge_disable,
.post_disable = dp_bridge_post_disable,
......@@ -68,6 +101,7 @@ static const struct drm_bridge_funcs dp_bridge_ops = {
.mode_valid = dp_bridge_mode_valid,
.get_modes = dp_bridge_get_modes,
.detect = dp_bridge_detect,
.atomic_check = dp_bridge_atomic_check,
};
struct drm_bridge *dp_bridge_init(struct msm_dp *dp_display, struct drm_device *dev,
......
......@@ -240,12 +240,12 @@ static int dp_parser_clock(struct dp_parser *parser)
return 0;
}
int dp_parser_find_next_bridge(struct dp_parser *parser)
int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser)
{
struct device *dev = &parser->pdev->dev;
struct platform_device *pdev = parser->pdev;
struct drm_bridge *bridge;
bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0);
bridge = devm_drm_of_get_bridge(dev, pdev->dev.of_node, 1, 0);
if (IS_ERR(bridge))
return PTR_ERR(bridge);
......
......@@ -138,8 +138,9 @@ struct dp_parser {
struct dp_parser *dp_parser_get(struct platform_device *pdev);
/**
* dp_parser_find_next_bridge() - find an additional bridge to DP
* devm_dp_parser_find_next_bridge() - find an additional bridge to DP
*
* @dev: device to tie bridge lifetime to
* @parser: dp_parser data from client
*
* This function is used to find any additional bridge attached to
......@@ -147,6 +148,6 @@ struct dp_parser *dp_parser_get(struct platform_device *pdev);
*
* Return: 0 if able to get the bridge, otherwise negative errno for failure.
*/
int dp_parser_find_next_bridge(struct dp_parser *parser);
int devm_dp_parser_find_next_bridge(struct device *dev, struct dp_parser *parser);
#endif
......@@ -218,6 +218,12 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
return -EINVAL;
priv = dev->dev_private;
if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) {
DRM_DEV_ERROR(dev->dev, "too many bridges\n");
return -ENOSPC;
}
msm_dsi->dev = dev;
ret = msm_dsi_host_modeset_init(msm_dsi->host, dev);
......
......@@ -300,6 +300,11 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
struct platform_device *pdev = hdmi->pdev;
int ret;
if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) {
DRM_DEV_ERROR(dev->dev, "too many bridges\n");
return -ENOSPC;
}
hdmi->dev = dev;
hdmi->encoder = encoder;
......@@ -339,7 +344,7 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
goto fail;
}
ret = devm_request_irq(&pdev->dev, hdmi->irq,
ret = devm_request_irq(dev->dev, hdmi->irq,
msm_hdmi_irq, IRQF_TRIGGER_HIGH,
"hdmi_isr", hdmi);
if (ret < 0) {
......
......@@ -247,6 +247,7 @@ static int msm_drm_uninit(struct device *dev)
for (i = 0; i < priv->num_bridges; i++)
drm_bridge_remove(priv->bridges[i]);
priv->num_bridges = 0;
pm_runtime_get_sync(dev);
msm_irq_uninstall(ddev);
......
......@@ -501,11 +501,11 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
*/
static void submit_cleanup(struct msm_gem_submit *submit, bool error)
{
unsigned cleanup_flags = BO_LOCKED | BO_OBJ_PINNED;
unsigned cleanup_flags = BO_LOCKED;
unsigned i;
if (error)
cleanup_flags |= BO_VMA_PINNED;
cleanup_flags |= BO_VMA_PINNED | BO_OBJ_PINNED;
for (i = 0; i < submit->nr_bos; i++) {
struct msm_gem_object *msm_obj = submit->bos[i].obj;
......@@ -706,7 +706,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
struct msm_drm_private *priv = dev->dev_private;
struct drm_msm_gem_submit *args = data;
struct msm_file_private *ctx = file->driver_priv;
struct msm_gem_submit *submit = NULL;
struct msm_gem_submit *submit;
struct msm_gpu *gpu = priv->gpu;
struct msm_gpu_submitqueue *queue;
struct msm_ringbuffer *ring;
......@@ -946,8 +946,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
put_unused_fd(out_fence_fd);
mutex_unlock(&queue->lock);
out_post_unlock:
if (submit)
msm_gem_submit_put(submit);
msm_gem_submit_put(submit);
if (!IS_ERR_OR_NULL(post_deps)) {
for (i = 0; i < args->nr_out_syncobjs; ++i) {
kfree(post_deps[i].chain);
......
......@@ -997,4 +997,6 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
}
msm_devfreq_cleanup(gpu);
platform_set_drvdata(gpu->pdev, NULL);
}
......@@ -280,6 +280,10 @@ struct msm_gpu {
static inline struct msm_gpu *dev_to_gpu(struct device *dev)
{
struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(dev);
if (!adreno_smmu)
return NULL;
return container_of(adreno_smmu, struct msm_gpu, adreno_smmu);
}
......
......@@ -25,7 +25,8 @@ static struct dma_fence *msm_job_run(struct drm_sched_job *job)
msm_gem_lock(obj);
msm_gem_unpin_vma_fenced(submit->bos[i].vma, fctx);
submit->bos[i].flags &= ~BO_VMA_PINNED;
msm_gem_unpin_locked(obj);
submit->bos[i].flags &= ~(BO_VMA_PINNED | BO_OBJ_PINNED);
msm_gem_unlock(obj);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment