Commit f8049dd8 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'msm-next' of git://people.freedesktop.org/~robclark/linux into drm-next

A bit smaller pull-req this time around.  Some continued DT binding
cleanup to get the corresponding dts bits merged upstream (through
other trees).  And explicit fence-fd support for submit ioctl.

* 'msm-next' of git://people.freedesktop.org/~robclark/linux:
  drm/msm: bump kernel api version for explicit fencing
  drm/msm: submit support for out-fences
  drm/msm: move fence allocation out of msm_gpu_submit()
  drm/msm: submit support for in-fences
  drm/msm: extend the submit ioctl to pass in flags
  drm/msm/mdp5: Set rotation property initial value to DRM_ROTATE_0 insted of 0
  drm/msm/hdmi: don't print error when adding i2c adapter fails
  drm/msm/mdp4: mark symbols static where possible
  drm/msm: Remove call to reservation_object_test_signaled_rcu before wait
  drm/msm/hdmi: Clean up HDMI gpio DT bindings
  drm/msm/mdp4: Fix issue with LCDC/LVDS port parsing
parents 3f346d5d 7a3bcc0a
...@@ -14,17 +14,16 @@ Required properties: ...@@ -14,17 +14,16 @@ Required properties:
- power-domains: Should be <&mmcc MDSS_GDSC>. - power-domains: Should be <&mmcc MDSS_GDSC>.
- clocks: device clocks - clocks: device clocks
See ../clocks/clock-bindings.txt for details. See ../clocks/clock-bindings.txt for details.
- qcom,hdmi-tx-ddc-clk-gpio: ddc clk pin
- qcom,hdmi-tx-ddc-data-gpio: ddc data pin
- qcom,hdmi-tx-hpd-gpio: hpd pin
- core-vdda-supply: phandle to supply regulator - core-vdda-supply: phandle to supply regulator
- hdmi-mux-supply: phandle to mux regulator - hdmi-mux-supply: phandle to mux regulator
- phys: the phandle for the HDMI PHY device - phys: the phandle for the HDMI PHY device
- phy-names: the name of the corresponding PHY device - phy-names: the name of the corresponding PHY device
Optional properties: Optional properties:
- qcom,hdmi-tx-mux-en-gpio: hdmi mux enable pin - hpd-gpios: hpd pin
- qcom,hdmi-tx-mux-sel-gpio: hdmi mux select pin - qcom,hdmi-tx-mux-en-gpios: hdmi mux enable pin
- qcom,hdmi-tx-mux-sel-gpios: hdmi mux select pin
- qcom,hdmi-tx-mux-lpm-gpios: hdmi mux lpm pin
- power-domains: reference to the power domain(s), if available. - power-domains: reference to the power domain(s), if available.
- pinctrl-names: the pin control state names; should contain "default" - pinctrl-names: the pin control state names; should contain "default"
- pinctrl-0: the default pinctrl state (active) - pinctrl-0: the default pinctrl state (active)
......
...@@ -11,6 +11,7 @@ config DRM_MSM ...@@ -11,6 +11,7 @@ config DRM_MSM
select TMPFS select TMPFS
select QCOM_SCM select QCOM_SCM
select SND_SOC_HDMI_CODEC if SND_SOC select SND_SOC_HDMI_CODEC if SND_SOC
select SYNC_FILE
default y default y
help help
DRM/KMS driver for MSM/snapdragon. DRM/KMS driver for MSM/snapdragon.
......
...@@ -422,11 +422,28 @@ static const struct { ...@@ -422,11 +422,28 @@ static const struct {
static int msm_hdmi_get_gpio(struct device_node *of_node, const char *name) static int msm_hdmi_get_gpio(struct device_node *of_node, const char *name)
{ {
int gpio = of_get_named_gpio(of_node, name, 0); int gpio;
/* try with the gpio names as in the table (downstream bindings) */
gpio = of_get_named_gpio(of_node, name, 0);
if (gpio < 0) { if (gpio < 0) {
char name2[32]; char name2[32];
snprintf(name2, sizeof(name2), "%s-gpio", name);
/* try with the gpio names as in the upstream bindings */
snprintf(name2, sizeof(name2), "%s-gpios", name);
gpio = of_get_named_gpio(of_node, name2, 0); gpio = of_get_named_gpio(of_node, name2, 0);
if (gpio < 0) {
char name3[32];
/*
* try again after stripping out the "qcom,hdmi-tx"
* prefix. This is mainly to match "hpd-gpios" used
* in the upstream bindings
*/
if (sscanf(name2, "qcom,hdmi-tx-%s", name3))
gpio = of_get_named_gpio(of_node, name3, 0);
}
if (gpio < 0) { if (gpio < 0) {
DBG("failed to get gpio: %s (%d)", name, gpio); DBG("failed to get gpio: %s (%d)", name, gpio);
gpio = -1; gpio = -1;
......
...@@ -243,7 +243,6 @@ void msm_hdmi_i2c_destroy(struct i2c_adapter *i2c) ...@@ -243,7 +243,6 @@ void msm_hdmi_i2c_destroy(struct i2c_adapter *i2c)
struct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi) struct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi)
{ {
struct drm_device *dev = hdmi->dev;
struct hdmi_i2c_adapter *hdmi_i2c; struct hdmi_i2c_adapter *hdmi_i2c;
struct i2c_adapter *i2c = NULL; struct i2c_adapter *i2c = NULL;
int ret; int ret;
...@@ -267,10 +266,8 @@ struct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi) ...@@ -267,10 +266,8 @@ struct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi)
i2c->algo = &msm_hdmi_i2c_algorithm; i2c->algo = &msm_hdmi_i2c_algorithm;
ret = i2c_add_adapter(i2c); ret = i2c_add_adapter(i2c);
if (ret) { if (ret)
dev_err(dev->dev, "failed to register hdmi i2c: %d\n", ret);
goto fail; goto fail;
}
return i2c; return i2c;
......
...@@ -228,18 +228,21 @@ static struct device_node *mdp4_detect_lcdc_panel(struct drm_device *dev) ...@@ -228,18 +228,21 @@ static struct device_node *mdp4_detect_lcdc_panel(struct drm_device *dev)
struct device_node *endpoint, *panel_node; struct device_node *endpoint, *panel_node;
struct device_node *np = dev->dev->of_node; struct device_node *np = dev->dev->of_node;
endpoint = of_graph_get_next_endpoint(np, NULL); /*
* LVDS/LCDC is the first port described in the list of ports in the
* MDP4 DT node.
*/
endpoint = of_graph_get_endpoint_by_regs(np, 0, -1);
if (!endpoint) { if (!endpoint) {
DBG("no endpoint in MDP4 to fetch LVDS panel\n"); DBG("no LVDS remote endpoint\n");
return NULL; return NULL;
} }
/* don't proceed if we have an endpoint but no panel_node tied to it */
panel_node = of_graph_get_remote_port_parent(endpoint); panel_node = of_graph_get_remote_port_parent(endpoint);
if (!panel_node) { if (!panel_node) {
dev_err(dev->dev, "no valid panel node\n"); DBG("no valid panel node in LVDS endpoint\n");
of_node_put(endpoint); of_node_put(endpoint);
return ERR_PTR(-ENODEV); return NULL;
} }
of_node_put(endpoint); of_node_put(endpoint);
...@@ -262,14 +265,12 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms, ...@@ -262,14 +265,12 @@ static int mdp4_modeset_init_intf(struct mdp4_kms *mdp4_kms,
switch (intf_type) { switch (intf_type) {
case DRM_MODE_ENCODER_LVDS: case DRM_MODE_ENCODER_LVDS:
/* /*
* bail out early if: * bail out early if there is no panel node (no need to
* - there is no panel node (no need to initialize lcdc * initialize LCDC encoder and LVDS connector)
* encoder and lvds connector), or
* - panel node is a bad pointer
*/ */
panel_node = mdp4_detect_lcdc_panel(dev); panel_node = mdp4_detect_lcdc_panel(dev);
if (IS_ERR_OR_NULL(panel_node)) if (!panel_node)
return PTR_ERR(panel_node); return 0;
encoder = mdp4_lcdc_encoder_init(dev, panel_node); encoder = mdp4_lcdc_encoder_init(dev, panel_node);
if (IS_ERR(encoder)) { if (IS_ERR(encoder)) {
......
...@@ -93,7 +93,7 @@ static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = { ...@@ -93,7 +93,7 @@ static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = {
}; };
/* this should probably be a helper: */ /* this should probably be a helper: */
struct drm_connector *get_connector(struct drm_encoder *encoder) static struct drm_connector *get_connector(struct drm_encoder *encoder)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
struct drm_connector *connector; struct drm_connector *connector;
......
...@@ -81,7 +81,7 @@ static void mdp4_plane_install_properties(struct drm_plane *plane, ...@@ -81,7 +81,7 @@ static void mdp4_plane_install_properties(struct drm_plane *plane,
// XXX // XXX
} }
int mdp4_plane_set_property(struct drm_plane *plane, static int mdp4_plane_set_property(struct drm_plane *plane,
struct drm_property *property, uint64_t val) struct drm_property *property, uint64_t val)
{ {
// XXX // XXX
......
...@@ -78,12 +78,12 @@ static void mdp5_plane_install_rotation_property(struct drm_device *dev, ...@@ -78,12 +78,12 @@ static void mdp5_plane_install_rotation_property(struct drm_device *dev,
if (!dev->mode_config.rotation_property) if (!dev->mode_config.rotation_property)
dev->mode_config.rotation_property = dev->mode_config.rotation_property =
drm_mode_create_rotation_property(dev, drm_mode_create_rotation_property(dev,
DRM_REFLECT_X | DRM_REFLECT_Y); DRM_ROTATE_0 | DRM_REFLECT_X | DRM_REFLECT_Y);
if (dev->mode_config.rotation_property) if (dev->mode_config.rotation_property)
drm_object_attach_property(&plane->base, drm_object_attach_property(&plane->base,
dev->mode_config.rotation_property, dev->mode_config.rotation_property,
0); DRM_ROTATE_0);
} }
/* helper to install properties which are common to planes and crtcs */ /* helper to install properties which are common to planes and crtcs */
......
...@@ -26,9 +26,10 @@ ...@@ -26,9 +26,10 @@
* MSM driver version: * MSM driver version:
* - 1.0.0 - initial interface * - 1.0.0 - initial interface
* - 1.1.0 - adds madvise, and support for submits with > 4 cmd buffers * - 1.1.0 - adds madvise, and support for submits with > 4 cmd buffers
* - 1.2.0 - adds explicit fence support for submit ioctl
*/ */
#define MSM_VERSION_MAJOR 1 #define MSM_VERSION_MAJOR 1
#define MSM_VERSION_MINOR 1 #define MSM_VERSION_MINOR 2
#define MSM_VERSION_PATCHLEVEL 0 #define MSM_VERSION_PATCHLEVEL 0
static void msm_fb_output_poll_changed(struct drm_device *dev) static void msm_fb_output_poll_changed(struct drm_device *dev)
......
...@@ -584,18 +584,16 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) ...@@ -584,18 +584,16 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
{ {
struct msm_gem_object *msm_obj = to_msm_bo(obj); struct msm_gem_object *msm_obj = to_msm_bo(obj);
bool write = !!(op & MSM_PREP_WRITE); bool write = !!(op & MSM_PREP_WRITE);
unsigned long remain =
if (op & MSM_PREP_NOSYNC) { op & MSM_PREP_NOSYNC ? 0 : timeout_to_jiffies(timeout);
if (!reservation_object_test_signaled_rcu(msm_obj->resv, write)) long ret;
return -EBUSY;
} else {
int ret;
ret = reservation_object_wait_timeout_rcu(msm_obj->resv, write, ret = reservation_object_wait_timeout_rcu(msm_obj->resv, write,
true, timeout_to_jiffies(timeout)); true, remain);
if (ret <= 0) if (ret == 0)
return ret == 0 ? -ETIMEDOUT : ret; return remain == 0 ? -EBUSY : -ETIMEDOUT;
} else if (ret < 0)
return ret;
/* TODO cache maintenance */ /* TODO cache maintenance */
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <linux/sync_file.h>
#include "msm_drv.h" #include "msm_drv.h"
#include "msm_gpu.h" #include "msm_gpu.h"
#include "msm_gem.h" #include "msm_gem.h"
...@@ -361,6 +363,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, ...@@ -361,6 +363,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
struct msm_file_private *ctx = file->driver_priv; struct msm_file_private *ctx = file->driver_priv;
struct msm_gem_submit *submit; struct msm_gem_submit *submit;
struct msm_gpu *gpu = priv->gpu; struct msm_gpu *gpu = priv->gpu;
struct fence *in_fence = NULL;
struct sync_file *sync_file = NULL;
int out_fence_fd = -1;
unsigned i; unsigned i;
int ret; int ret;
...@@ -370,13 +375,24 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, ...@@ -370,13 +375,24 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
/* for now, we just have 3d pipe.. eventually this would need to /* for now, we just have 3d pipe.. eventually this would need to
* be more clever to dispatch to appropriate gpu module: * be more clever to dispatch to appropriate gpu module:
*/ */
if (args->pipe != MSM_PIPE_3D0) if (MSM_PIPE_ID(args->flags) != MSM_PIPE_3D0)
return -EINVAL;
if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS)
return -EINVAL; return -EINVAL;
ret = mutex_lock_interruptible(&dev->struct_mutex); ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret) if (ret)
return ret; return ret;
if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
if (out_fence_fd < 0) {
ret = out_fence_fd;
goto out_unlock;
}
}
submit = submit_create(dev, gpu, args->nr_bos, args->nr_cmds); submit = submit_create(dev, gpu, args->nr_bos, args->nr_cmds);
if (!submit) { if (!submit) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -391,9 +407,32 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, ...@@ -391,9 +407,32 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
if (ret) if (ret)
goto out; goto out;
if (args->flags & MSM_SUBMIT_FENCE_FD_IN) {
in_fence = sync_file_get_fence(args->fence_fd);
if (!in_fence) {
ret = -EINVAL;
goto out;
}
/* TODO if we get an array-fence due to userspace merging multiple
* fences, we need a way to determine if all the backing fences
* are from our own context..
*/
if (in_fence->context != gpu->fctx->context) {
ret = fence_wait(in_fence, true);
if (ret)
goto out;
}
}
if (!(args->fence & MSM_SUBMIT_NO_IMPLICIT)) {
ret = submit_fence_sync(submit); ret = submit_fence_sync(submit);
if (ret) if (ret)
goto out; goto out;
}
ret = submit_pin_objects(submit); ret = submit_pin_objects(submit);
if (ret) if (ret)
...@@ -459,15 +498,39 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, ...@@ -459,15 +498,39 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
submit->nr_cmds = i; submit->nr_cmds = i;
ret = msm_gpu_submit(gpu, submit, ctx); submit->fence = msm_fence_alloc(gpu->fctx);
if (IS_ERR(submit->fence)) {
ret = PTR_ERR(submit->fence);
submit->fence = NULL;
goto out;
}
if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
sync_file = sync_file_create(submit->fence);
if (!sync_file) {
ret = -ENOMEM;
goto out;
}
}
msm_gpu_submit(gpu, submit, ctx);
args->fence = submit->fence->seqno; args->fence = submit->fence->seqno;
if (args->flags & MSM_SUBMIT_FENCE_FD_OUT) {
fd_install(out_fence_fd, sync_file->file);
args->fence_fd = out_fence_fd;
}
out: out:
if (in_fence)
fence_put(in_fence);
submit_cleanup(submit); submit_cleanup(submit);
if (ret) if (ret)
msm_gem_submit_free(submit); msm_gem_submit_free(submit);
out_unlock: out_unlock:
if (ret && (out_fence_fd >= 0))
put_unused_fd(out_fence_fd);
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return ret; return ret;
} }
...@@ -509,22 +509,15 @@ void msm_gpu_retire(struct msm_gpu *gpu) ...@@ -509,22 +509,15 @@ void msm_gpu_retire(struct msm_gpu *gpu)
} }
/* add bo's to gpu's ring, and kick gpu: */ /* add bo's to gpu's ring, and kick gpu: */
int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
struct msm_file_private *ctx) struct msm_file_private *ctx)
{ {
struct drm_device *dev = gpu->dev; struct drm_device *dev = gpu->dev;
struct msm_drm_private *priv = dev->dev_private; struct msm_drm_private *priv = dev->dev_private;
int i, ret; int i;
WARN_ON(!mutex_is_locked(&dev->struct_mutex)); WARN_ON(!mutex_is_locked(&dev->struct_mutex));
submit->fence = msm_fence_alloc(gpu->fctx);
if (IS_ERR(submit->fence)) {
ret = PTR_ERR(submit->fence);
submit->fence = NULL;
return ret;
}
inactive_cancel(gpu); inactive_cancel(gpu);
list_add_tail(&submit->node, &gpu->submit_list); list_add_tail(&submit->node, &gpu->submit_list);
...@@ -557,8 +550,6 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, ...@@ -557,8 +550,6 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
priv->lastctx = ctx; priv->lastctx = ctx;
hangcheck_timer_reset(gpu); hangcheck_timer_reset(gpu);
return 0;
} }
/* /*
......
...@@ -163,7 +163,7 @@ int msm_gpu_perfcntr_sample(struct msm_gpu *gpu, uint32_t *activetime, ...@@ -163,7 +163,7 @@ int msm_gpu_perfcntr_sample(struct msm_gpu *gpu, uint32_t *activetime,
uint32_t *totaltime, uint32_t ncntrs, uint32_t *cntrs); uint32_t *totaltime, uint32_t ncntrs, uint32_t *cntrs);
void msm_gpu_retire(struct msm_gpu *gpu); void msm_gpu_retire(struct msm_gpu *gpu);
int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
struct msm_file_private *ctx); struct msm_file_private *ctx);
int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
......
...@@ -42,6 +42,15 @@ extern "C" { ...@@ -42,6 +42,15 @@ extern "C" {
#define MSM_PIPE_2D1 0x02 #define MSM_PIPE_2D1 0x02
#define MSM_PIPE_3D0 0x10 #define MSM_PIPE_3D0 0x10
/* The pipe-id just uses the lower bits, so can be OR'd with flags in
* the upper 16 bits (which could be extended further, if needed, maybe
* we extend/overload the pipe-id some day to deal with multiple rings,
* but even then I don't think we need the full lower 16 bits).
*/
#define MSM_PIPE_ID_MASK 0xffff
#define MSM_PIPE_ID(x) ((x) & MSM_PIPE_ID_MASK)
#define MSM_PIPE_FLAGS(x) ((x) & ~MSM_PIPE_ID_MASK)
/* timeouts are specified in clock-monotonic absolute times (to simplify /* timeouts are specified in clock-monotonic absolute times (to simplify
* restarting interrupted ioctls). The following struct is logically the * restarting interrupted ioctls). The following struct is logically the
* same as 'struct timespec' but 32/64b ABI safe. * same as 'struct timespec' but 32/64b ABI safe.
...@@ -175,17 +184,28 @@ struct drm_msm_gem_submit_bo { ...@@ -175,17 +184,28 @@ struct drm_msm_gem_submit_bo {
__u64 presumed; /* in/out, presumed buffer address */ __u64 presumed; /* in/out, presumed buffer address */
}; };
/* Valid submit ioctl flags: */
#define MSM_SUBMIT_NO_IMPLICIT 0x80000000 /* disable implicit sync */
#define MSM_SUBMIT_FENCE_FD_IN 0x40000000 /* enable input fence_fd */
#define MSM_SUBMIT_FENCE_FD_OUT 0x20000000 /* enable output fence_fd */
#define MSM_SUBMIT_FLAGS ( \
MSM_SUBMIT_NO_IMPLICIT | \
MSM_SUBMIT_FENCE_FD_IN | \
MSM_SUBMIT_FENCE_FD_OUT | \
0)
/* Each cmdstream submit consists of a table of buffers involved, and /* Each cmdstream submit consists of a table of buffers involved, and
* one or more cmdstream buffers. This allows for conditional execution * one or more cmdstream buffers. This allows for conditional execution
* (context-restore), and IB buffers needed for per tile/bin draw cmds. * (context-restore), and IB buffers needed for per tile/bin draw cmds.
*/ */
struct drm_msm_gem_submit { struct drm_msm_gem_submit {
__u32 pipe; /* in, MSM_PIPE_x */ __u32 flags; /* MSM_PIPE_x | MSM_SUBMIT_x */
__u32 fence; /* out */ __u32 fence; /* out */
__u32 nr_bos; /* in, number of submit_bo's */ __u32 nr_bos; /* in, number of submit_bo's */
__u32 nr_cmds; /* in, number of submit_cmd's */ __u32 nr_cmds; /* in, number of submit_cmd's */
__u64 __user bos; /* in, ptr to array of submit_bo's */ __u64 __user bos; /* in, ptr to array of submit_bo's */
__u64 __user cmds; /* in, ptr to array of submit_cmd's */ __u64 __user cmds; /* in, ptr to array of submit_cmd's */
__s32 fence_fd; /* in/out fence fd (see MSM_SUBMIT_FENCE_FD_IN/OUT) */
}; };
/* The normal way to synchronize with the GPU is just to CPU_PREP on /* The normal way to synchronize with the GPU is just to CPU_PREP on
......
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