This small series of patches adds support for the 3D engine found on NVIDIA Tegra SoCs. It builds on top of Terje's and Arto's host1x and gr2d patches. A couple of things still need to be done before this can be merged, though.
Patch 1 is the central piece of the series. It adds support for using the gr3d engine via the same DRM IOCTLs that gr2d uses. A very basic set of programs to test this can be found here[0].
Patch 2 adds support for the XBGR8888 format, which seems to be what most gr3d programs use. It also adds the RGB565 as a format supported by planes. This latter part could be moved to a separate patch, but I didn't think that was necessary.
Patch 3 finally allows buffer objects to be marked as tiled so that the display controller can scan them out appropriately.
Thierry
[0]: https://github.com/organizations/grate-driver
Thierry Reding (3): WIP: drm/tegra: Add 3D support drm/tegra: Support the XBGR8888 pixelformat drm/tegra: Add support for tiled buffer objects
drivers/gpu/host1x/Makefile | 1 + drivers/gpu/host1x/dev.c | 7 + drivers/gpu/host1x/dev.h | 1 + drivers/gpu/host1x/drm/dc.c | 16 +++ drivers/gpu/host1x/drm/dc.h | 4 + drivers/gpu/host1x/drm/drm.c | 4 +- drivers/gpu/host1x/drm/drm.h | 2 + drivers/gpu/host1x/drm/fb.c | 12 +- drivers/gpu/host1x/drm/gem.c | 20 ++- drivers/gpu/host1x/drm/gem.h | 13 +- drivers/gpu/host1x/drm/gr3d.c | 289 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/host1x/host1x.h | 3 +- include/uapi/drm/tegra_drm.h | 2 + 13 files changed, 360 insertions(+), 14 deletions(-) create mode 100644 drivers/gpu/host1x/drm/gr3d.c
This is a preliminary patch that adds support for 3D support on top of Terje's and Arto's host1x and gr2d patches.
There are a few things that still need to be resolved before this can be applied. I haven't been able to test Tegra30 support so it'd be good if somebody with hardware could give it a try. I can probably arrange to test it on a CardHu if nobody else steps up, but it'll take a while until I get that setup. Looking at the downstream kernels indicates that Tegra30 has a second clock and powergate domain and if those really are required then this patch won't work on Tegra30.
One other important piece that is missing is a list of address registers to feed to the firewall so that submitted command streams can be checked for validity. I've already talked to Terje about that, but it seems like it may turn out to be problematic. What with NVIDIA not wanting to provide the register descriptions and all that. We'll need to resolve this in some way before this patch can be merged.
Finally I want to refactor some of the commonalities between gr2d and gr3d so that they can share more code.
If people want to give this a spin, there are some very basic test programs available here[0]. The tests from the grate repository are probably the most useful right now since they test both the gr2d and gr3d modules and therefore can be used to verify that this patch actually works.
[0]: https://github.com/organizations/grate-driver
Signed-off-by: Thierry Reding thierry.reding@avionic-design.de --- drivers/gpu/host1x/Makefile | 1 + drivers/gpu/host1x/dev.c | 7 + drivers/gpu/host1x/dev.h | 1 + drivers/gpu/host1x/drm/drm.c | 2 + drivers/gpu/host1x/drm/gr3d.c | 289 ++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/host1x/host1x.h | 3 +- 6 files changed, 302 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/host1x/drm/gr3d.c
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile index 3b037b6..5802e1b 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -17,4 +17,5 @@ host1x-$(CONFIG_DRM_TEGRA) += drm/drm.o drm/fb.o drm/dc.o host1x-$(CONFIG_DRM_TEGRA) += drm/output.o drm/rgb.o drm/hdmi.o host1x-$(CONFIG_DRM_TEGRA) += drm/gem.o host1x-$(CONFIG_DRM_TEGRA) += drm/gr2d.o +host1x-$(CONFIG_DRM_TEGRA) += drm/gr3d.o obj-$(CONFIG_TEGRA_HOST1X) += host1x.o diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 28e28a2..6daa3be 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -213,11 +213,17 @@ static int __init tegra_host1x_init(void) err = platform_driver_register(&tegra_gr2d_driver); if (err < 0) goto unregister_hdmi; + + err = platform_driver_register(&tegra_gr3d_driver); + if (err < 0) + goto unregister_gr2d; #endif
return 0;
#ifdef CONFIG_DRM_TEGRA +unregister_gr2d: + platform_driver_unregister(&tegra_gr2d_driver); unregister_hdmi: platform_driver_unregister(&tegra_hdmi_driver); unregister_dc: @@ -232,6 +238,7 @@ module_init(tegra_host1x_init); static void __exit tegra_host1x_exit(void) { #ifdef CONFIG_DRM_TEGRA + platform_driver_unregister(&tegra_gr3d_driver); platform_driver_unregister(&tegra_gr2d_driver); platform_driver_unregister(&tegra_hdmi_driver); platform_driver_unregister(&tegra_dc_driver); diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index a1607d6..406237a 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -304,5 +304,6 @@ static inline void host1x_hw_show_mlocks(struct host1x *host, struct output *o) extern struct platform_driver tegra_hdmi_driver; extern struct platform_driver tegra_dc_driver; extern struct platform_driver tegra_gr2d_driver; +extern struct platform_driver tegra_gr3d_driver;
#endif diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c index 2b561c9..298c5f0 100644 --- a/drivers/gpu/host1x/drm/drm.c +++ b/drivers/gpu/host1x/drm/drm.c @@ -85,9 +85,11 @@ static int host1x_parse_dt(struct host1x_drm *host1x) "nvidia,tegra20-dc", "nvidia,tegra20-hdmi", "nvidia,tegra20-gr2d", + "nvidia,tegra20-gr3d", "nvidia,tegra30-dc", "nvidia,tegra30-hdmi", "nvidia,tegra30-gr2d", + "nvidia,tegra30-gr3d", }; unsigned int i; int err; diff --git a/drivers/gpu/host1x/drm/gr3d.c b/drivers/gpu/host1x/drm/gr3d.c new file mode 100644 index 0000000..58fe791 --- /dev/null +++ b/drivers/gpu/host1x/drm/gr3d.c @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2013 Avionic Design GmbH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/tegra-powergate.h> + +#include "host1x_client.h" +#include "channel.h" +#include "drm.h" +#include "gem.h" +#include "job.h" +#include "syncpt.h" + +struct gr3d { + struct host1x_client client; + struct host1x_channel *channel; + struct clk *clk; +}; + +static inline struct gr3d *to_gr3d(struct host1x_client *client) +{ + return container_of(client, struct gr3d, client); +} + +static int gr3d_drm_init(struct host1x_client *client, struct drm_device *drm) +{ + return 0; +} + +static int gr3d_drm_exit(struct host1x_client *client) +{ + return 0; +} + +static int gr3d_open_channel(struct host1x_client *client, + struct host1x_drm_context *context) +{ + struct gr3d *gr3d = to_gr3d(client); + + context->channel = host1x_channel_get(gr3d->channel); + if (!context->channel) + return -ENOMEM; + + return 0; +} + +static void gr3d_close_channel(struct host1x_drm_context *context) +{ + host1x_channel_put(context->channel); +} + +static struct host1x_bo *host1x_bo_lookup(struct drm_device *drm, + struct drm_file *file, + u32 handle) +{ + struct drm_gem_object *gem; + struct tegra_bo *bo; + + gem = drm_gem_object_lookup(drm, file, handle); + if (!gem) + return 0; + + mutex_lock(&drm->struct_mutex); + drm_gem_object_unreference(gem); + mutex_unlock(&drm->struct_mutex); + + bo = to_tegra_bo(gem); + return &bo->base; +} + +static int gr3d_is_addr_reg(struct device *dev, u32 class, u32 reg) +{ + return 0; +} + +static int gr3d_submit(struct host1x_drm_context *context, + struct drm_tegra_submit *args, struct drm_device *drm, + struct drm_file *file) +{ + struct host1x_job *job; + unsigned int num_cmdbufs = args->num_cmdbufs; + unsigned int num_relocs = args->num_relocs; + unsigned int num_waitchks = args->num_waitchks; + struct drm_tegra_cmdbuf __user *cmdbufs = + (void * __user)(uintptr_t)args->cmdbufs; + struct drm_tegra_reloc __user *relocs = + (void * __user)(uintptr_t)args->relocs; + struct drm_tegra_waitchk __user *waitchks = + (void * __user)(uintptr_t)args->waitchks; + struct drm_tegra_syncpt syncpt; + int err; + + /* We don't yet support other than one syncpt_incr struct per submit */ + if (args->num_syncpts != 1) + return -EINVAL; + + job = host1x_job_alloc(context->channel, args->num_cmdbufs, + args->num_relocs, args->num_waitchks); + if (!job) + return -ENOMEM; + + job->num_relocs = args->num_relocs; + job->num_waitchk = args->num_waitchks; + job->client = (u32)args->context; + job->class = context->client->class; + job->serialize = true; + + while (num_cmdbufs) { + struct drm_tegra_cmdbuf cmdbuf; + struct host1x_bo *bo; + + err = copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf)); + if (err) + goto fail; + + bo = host1x_bo_lookup(drm, file, cmdbuf.handle); + if (!bo) + goto fail; + + host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset); + num_cmdbufs--; + cmdbufs++; + } + + err = copy_from_user(job->relocarray, relocs, + sizeof(*relocs) * num_relocs); + if (err) + goto fail; + + while (num_relocs--) { + struct host1x_reloc *reloc = &job->relocarray[num_relocs]; + struct host1x_bo *cmdbuf, *target; + + cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf); + target = host1x_bo_lookup(drm, file, (u32)reloc->target); + + reloc->cmdbuf = cmdbuf; + reloc->target = target; + + if (!reloc->target || !reloc->cmdbuf) + goto fail; + } + + err = copy_from_user(job->waitchk, waitchks, + sizeof(*waitchks) * num_waitchks); + if (err) + goto fail; + + err = host1x_job_pin(job, context->client->dev); + if (err) + goto fail; + + err = copy_from_user(&syncpt, (void * __user)(uintptr_t)args->syncpts, + sizeof(syncpt)); + if (err) + goto fail; + + job->syncpt_id = syncpt.id; + job->syncpt_incrs = syncpt.incrs; + job->timeout = 10000; + job->is_addr_reg = gr3d_is_addr_reg; + if (args->timeout && args->timeout < 10000) + job->timeout = args->timeout; + + err = host1x_job_submit(job); + if (err) + goto fail_submit; + + args->fence = job->syncpt_end; + + host1x_job_put(job); + return 0; + +fail_submit: + host1x_job_unpin(job); +fail: + host1x_job_put(job); + return err; +} + +static const struct host1x_client_ops gr3d_client_ops = { + .drm_init = gr3d_drm_init, + .drm_exit = gr3d_drm_exit, + .open_channel = gr3d_open_channel, + .close_channel = gr3d_close_channel, + .submit = gr3d_submit, +}; + +static int gr3d_probe(struct platform_device *pdev) +{ + struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent); + struct host1x_syncpt **syncpts; + struct gr3d *gr3d; + int err; + + gr3d = devm_kzalloc(&pdev->dev, sizeof(*gr3d), GFP_KERNEL); + if (!gr3d) + return -ENOMEM; + + syncpts = devm_kzalloc(&pdev->dev, 1 * sizeof(*syncpts), GFP_KERNEL); + if (!syncpts) + return -ENOMEM; + + gr3d->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(gr3d->clk)) { + dev_err(&pdev->dev, "cannot get clock\n"); + return PTR_ERR(gr3d->clk); + } + + err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_3D, gr3d->clk); + if (err < 0) { + dev_err(&pdev->dev, "failed to power up 3D unit\n"); + return err; + } + + gr3d->channel = host1x_channel_request(&pdev->dev); + if (!gr3d->channel) + return -ENOMEM; + + syncpts[0] = host1x_syncpt_request(&pdev->dev, 0); + if (!syncpts[0]) { + host1x_channel_free(gr3d->channel); + return -ENOMEM; + } + + gr3d->client.class = HOST1X_CLASS_GR3D; + gr3d->client.ops = &gr3d_client_ops; + gr3d->client.dev = &pdev->dev; + + gr3d->client.syncpts = syncpts; + gr3d->client.num_syncpts = 1; + + err = host1x_register_client(host1x, &gr3d->client); + if (err < 0) { + dev_err(&pdev->dev, "failed to register host1x client: %d\n", + err); + return err; + } + + platform_set_drvdata(pdev, gr3d); + + return 0; +} + +static int __exit gr3d_remove(struct platform_device *pdev) +{ + struct host1x_drm *host1x = host1x_get_drm_data(pdev->dev.parent); + struct gr3d *gr3d = platform_get_drvdata(pdev); + unsigned int i; + int err; + + err = host1x_unregister_client(host1x, &gr3d->client); + if (err < 0) { + dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", + err); + return err; + } + + for (i = 0; i < gr3d->client.num_syncpts; i++) + host1x_syncpt_free(gr3d->client.syncpts[i]); + + host1x_channel_free(gr3d->channel); + clk_disable_unprepare(gr3d->clk); + + return 0; +} + +static const struct of_device_id tegra_gr3d_match[] = { + { .compatible = "nvidia,tegra30-gr3d" }, + { .compatible = "nvidia,tegra20-gr3d" }, + { } +}; + +struct platform_driver tegra_gr3d_driver = { + .probe = gr3d_probe, + .remove = __exit_p(gr3d_remove), + .driver = { + .owner = THIS_MODULE, + .name = "gr3d", + .of_match_table = tegra_gr3d_match, + }, +}; diff --git a/drivers/gpu/host1x/host1x.h b/drivers/gpu/host1x/host1x.h index a2bc1e6..70dfe56 100644 --- a/drivers/gpu/host1x/host1x.h +++ b/drivers/gpu/host1x/host1x.h @@ -24,7 +24,8 @@ enum host1x_class { HOST1X_CLASS_HOST1X = 0x1, HOST1X_CLASS_GR2D = 0x51, - HOST1X_CLASS_GR2D_SB = 0x52 + HOST1X_CLASS_GR2D_SB = 0x52, + HOST1X_CLASS_GR3D = 0x60, };
#endif
While at it, also include the RGB565 pixelformat in the list of formats supported by overlays.
Signed-off-by: Thierry Reding thierry.reding@avionic-design.de --- drivers/gpu/host1x/drm/dc.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c index edfe0ee..14a09a4 100644 --- a/drivers/gpu/host1x/drm/dc.c +++ b/drivers/gpu/host1x/drm/dc.c @@ -108,7 +108,9 @@ static const struct drm_plane_funcs tegra_plane_funcs = { };
static const uint32_t plane_formats[] = { + DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB565, DRM_FORMAT_UYVY, DRM_FORMAT_YUV420, DRM_FORMAT_YUV422, @@ -546,6 +548,9 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, unsigned int tegra_dc_format(uint32_t format) { switch (format) { + case DRM_FORMAT_XBGR8888: + return WIN_COLOR_DEPTH_R8G8B8A8; + case DRM_FORMAT_XRGB8888: return WIN_COLOR_DEPTH_B8G8R8A8;
The gr2d and gr3d engines work more efficiently on buffers with a tiled memory layout. Allow created buffers to be marked as tiled so that the display controller can scan them out properly.
Signed-off-by: Thierry Reding thierry.reding@avionic-design.de --- drivers/gpu/host1x/drm/dc.c | 11 +++++++++++ drivers/gpu/host1x/drm/dc.h | 4 ++++ drivers/gpu/host1x/drm/drm.c | 2 +- drivers/gpu/host1x/drm/drm.h | 2 ++ drivers/gpu/host1x/drm/fb.c | 12 +++++++++++- drivers/gpu/host1x/drm/gem.c | 20 +++++++++++++------- drivers/gpu/host1x/drm/gem.h | 13 +++++++++---- include/uapi/drm/tegra_drm.h | 2 ++ 8 files changed, 53 insertions(+), 13 deletions(-)
diff --git a/drivers/gpu/host1x/drm/dc.c b/drivers/gpu/host1x/drm/dc.c index 14a09a4..5a0d111 100644 --- a/drivers/gpu/host1x/drm/dc.c +++ b/drivers/gpu/host1x/drm/dc.c @@ -51,6 +51,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, window.dst.h = crtc_h; window.format = tegra_dc_format(fb->pixel_format); window.bits_per_pixel = fb->bits_per_pixel; + window.tiled = tegra_fb_is_tiled(fb);
for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { struct tegra_bo *bo = tegra_fb_get_plane(fb, i); @@ -492,6 +493,16 @@ int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
+ if (window->tiled) { + value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | + DC_WIN_BUFFER_ADDR_MODE_TILE; + } else { + value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | + DC_WIN_BUFFER_ADDR_MODE_LINEAR; + } + + tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); + value = WIN_ENABLE;
if (yuv) { diff --git a/drivers/gpu/host1x/drm/dc.h b/drivers/gpu/host1x/drm/dc.h index 79eaec9..e8da0ba 100644 --- a/drivers/gpu/host1x/drm/dc.h +++ b/drivers/gpu/host1x/drm/dc.h @@ -365,6 +365,10 @@ #define DC_WIN_BUF_STRIDE 0x70b #define DC_WIN_UV_BUF_STRIDE 0x70c #define DC_WIN_BUFFER_ADDR_MODE 0x70d +#define DC_WIN_BUFFER_ADDR_MODE_LINEAR (0 << 0) +#define DC_WIN_BUFFER_ADDR_MODE_TILE (1 << 0) +#define DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV (0 << 16) +#define DC_WIN_BUFFER_ADDR_MODE_TILE_UV (1 << 16) #define DC_WIN_DV_CONTROL 0x70e
#define DC_WIN_BLEND_NOKEY 0x70f diff --git a/drivers/gpu/host1x/drm/drm.c b/drivers/gpu/host1x/drm/drm.c index 298c5f0..33d04c3 100644 --- a/drivers/gpu/host1x/drm/drm.c +++ b/drivers/gpu/host1x/drm/drm.c @@ -328,7 +328,7 @@ static int tegra_gem_create(struct drm_device *drm, void *data, struct drm_tegra_gem_create *args = data; struct tegra_bo *bo;
- bo = tegra_bo_create_with_handle(file, drm, args->size, + bo = tegra_bo_create_with_handle(file, drm, args->size, args->flags, &args->handle); if (IS_ERR(bo)) return PTR_ERR(bo); diff --git a/drivers/gpu/host1x/drm/drm.h b/drivers/gpu/host1x/drm/drm.h index 02ce020..fd1f373 100644 --- a/drivers/gpu/host1x/drm/drm.h +++ b/drivers/gpu/host1x/drm/drm.h @@ -162,6 +162,7 @@ struct tegra_dc_window { unsigned int format; unsigned int stride[2]; unsigned long base[3]; + bool tiled; };
/* from dc.c */ @@ -262,6 +263,7 @@ extern int tegra_output_exit(struct tegra_output *output); /* from fb.c */ struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, unsigned int index); +bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); extern int tegra_drm_fb_init(struct drm_device *drm); extern void tegra_drm_fb_exit(struct drm_device *drm); extern void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev); diff --git a/drivers/gpu/host1x/drm/fb.c b/drivers/gpu/host1x/drm/fb.c index 953e418..b8b3c21 100644 --- a/drivers/gpu/host1x/drm/fb.c +++ b/drivers/gpu/host1x/drm/fb.c @@ -34,6 +34,16 @@ struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, return fb->planes[index]; }
+bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer) +{ + struct tegra_fb *fb = to_tegra_fb(framebuffer); + + if (fb->planes[0]->flags & TEGRA_BO_TILED) + return true; + + return false; +} + static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) { struct tegra_fb *fb = to_tegra_fb(framebuffer); @@ -188,7 +198,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
size = cmd.pitches[0] * cmd.height;
- bo = tegra_bo_create(drm, size); + bo = tegra_bo_create(drm, size, 0); if (IS_ERR(bo)) return PTR_ERR(bo);
diff --git a/drivers/gpu/host1x/drm/gem.c b/drivers/gpu/host1x/drm/gem.c index c5e9a9b..0bdbb50 100644 --- a/drivers/gpu/host1x/drm/gem.c +++ b/drivers/gpu/host1x/drm/gem.c @@ -24,6 +24,7 @@ #include <linux/export.h> #include <linux/dma-mapping.h>
+#include <drm/tegra_drm.h> #include <drm/drmP.h> #include <drm/drm.h>
@@ -111,7 +112,8 @@ unsigned int tegra_bo_get_mmap_offset(struct tegra_bo *bo) return (unsigned int)bo->gem.map_list.hash.key << PAGE_SHIFT; }
-struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size) +struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, + unsigned long flags) { struct tegra_bo *bo; int err; @@ -140,6 +142,9 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size) if (err) goto err_mmap;
+ if (flags & DRM_TEGRA_GEM_CREATE_TILED) + bo->flags |= TEGRA_BO_TILED; + return bo;
err_mmap: @@ -154,14 +159,15 @@ err_dma: }
struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, - struct drm_device *drm, - unsigned int size, - unsigned int *handle) + struct drm_device *drm, + unsigned int size, + unsigned long flags, + unsigned int *handle) { struct tegra_bo *bo; int ret;
- bo = tegra_bo_create(drm, size); + bo = tegra_bo_create(drm, size, flags); if (IS_ERR(bo)) return bo;
@@ -203,8 +209,8 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, if (args->size < args->pitch * args->height) args->size = args->pitch * args->height;
- bo = tegra_bo_create_with_handle(file, drm, args->size, - &args->handle); + bo = tegra_bo_create_with_handle(file, drm, args->size, 0, + &args->handle); if (IS_ERR(bo)) return PTR_ERR(bo);
diff --git a/drivers/gpu/host1x/drm/gem.h b/drivers/gpu/host1x/drm/gem.h index 34de2b4..a8fc68a 100644 --- a/drivers/gpu/host1x/drm/gem.h +++ b/drivers/gpu/host1x/drm/gem.h @@ -24,9 +24,12 @@
#include "host1x_bo.h"
+#define TEGRA_BO_TILED (1 << 0) + struct tegra_bo { struct drm_gem_object gem; struct host1x_bo base; + unsigned long flags; dma_addr_t paddr; void *vaddr; }; @@ -38,11 +41,13 @@ static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
extern const struct host1x_bo_ops tegra_bo_ops;
-struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size); +struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size, + unsigned long flags); struct tegra_bo *tegra_bo_create_with_handle(struct drm_file *file, - struct drm_device *drm, - unsigned int size, - unsigned int *handle); + struct drm_device *drm, + unsigned int size, + unsigned long flags, + unsigned int *handle); void tegra_bo_free_object(struct drm_gem_object *gem); unsigned int tegra_bo_get_mmap_offset(struct tegra_bo *bo); int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index 6e132a2..8b9424a 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h @@ -17,6 +17,8 @@ #ifndef _UAPI_TEGRA_DRM_H_ #define _UAPI_TEGRA_DRM_H_
+#define DRM_TEGRA_GEM_CREATE_TILED (1 << 0) + struct drm_tegra_gem_create { __u64 size; __u32 flags;
On Thu, Apr 04, 2013 at 04:09:17PM +0200, Thierry Reding wrote: [...]
This apparently redirects to github.com unless you're a member of the grate-driver organization. So the correct link should actually be:
https://github.com/grate-driver
Thanks Rob for pointing this out!
Thierry
dri-devel@lists.freedesktop.org