Merge remote-tracking branch 'msm/msm-fixes' into HEAD
This commit is contained in:
commit
9a5c1586e8
@ -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 @@ out:
|
||||
|
||||
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 @@ out:
|
||||
*/
|
||||
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 @@ out_unlock:
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user