mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 10:13:57 +08:00
drm/tegra: Changes for v3.17-rc1
Mostly some cleanup all over the place. Pitch alignment limitations of the display controller are now honored and job submission is 64-bit safe. The SOR output (used for eDP) properly configures sync signal polarities according to the display mode rather than hard-coding them to some value and the number of bits per color is now taken from the panel rather than hard-coded to properly support 24-bit vs. 18-bit panels. The DSI controller now properly supports non-continuous clock mode. GEM objects can now have their flags and tiling mode modified via IOCTLs to allow buffers imported from Nouveau to be properly displayed. Newer generations of the Tegra display controller can also detile block linear buffers at scan-out time. Finally the driver now properly exports MODULE_DEVICE_TABLEs to allow it to be automatically loaded when built as a module. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABAgAGBQJT4kgqAAoJEN0jrNd/PrOhwSUP/ja3Szs8mdKzRtDcmUla7pIU g6dVTrXibruWQtB4Mf0Zv/7vVHDAuVW3q01lRHamud9g+Ci74YDsd99AJuguBQqy m0wNm2GFye64pcc/QdpmpH6zUEtt/eULxKYWco3jxGaMtH+v051qIyXE7JhS2KNo vE0XUV6bQPQWfhBr94IqJL79lO/DaNOKYuGATh3g6o/D/R+EFjNod7vZ7wGjpzoG LFqCsTfMA80sv/S19GLCwX/m/DbVVjPHPl1AxRNz5KhWXguo+teQ+0hKJ3t635IE xkW9GJ5Ghuq524sLNY+kEwAiuGVOotFIFqy9lPFNQllp7tyyK0uaWaQHbINYPso9 3QW4qdGfoioYzg6OzpLMQLwiHwl37z9oaDRodb+tZr9DGfrZ2GihTJwZIqLezBhD KGwDUb6/mexuotn6bg3QavFGgGKxrzb/rmiC/o4wJie6gSw3fJLzhOs1fgcus5p8 NcSRWkl90wbuoVE2h9I3mdHi4A+dAkAR9K6e8UxQCGfJwfisSeYABqh/UvRxNs3u mp8fIBbEmUKr6Kznaehw6VBy4xd6yp6hpjMJjPClNS4oErXuzhvZdoKjma7Jg6wj 7KFNSs1R1euNRjRX2J7ITPz7sIkjac5Ms2ejeniG5+RpqWp4c54G2MxuhvbFlVEA GOZYuKjSn6IEOkR5cx/X =qYgE -----END PGP SIGNATURE----- Merge tag 'drm/tegra/for-3.17-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next drm/tegra: Changes for v3.17-rc1 Mostly some cleanup all over the place. Pitch alignment limitations of the display controller are now honored and job submission is 64-bit safe. The SOR output (used for eDP) properly configures sync signal polarities according to the display mode rather than hard-coding them to some value and the number of bits per color is now taken from the panel rather than hard-coded to properly support 24-bit vs. 18-bit panels. The DSI controller now properly supports non-continuous clock mode. GEM objects can now have their flags and tiling mode modified via IOCTLs to allow buffers imported from Nouveau to be properly displayed. Newer generations of the Tegra display controller can also detile block linear buffers at scan-out time. Finally the driver now properly exports MODULE_DEVICE_TABLEs to allow it to be automatically loaded when built as a module. * tag 'drm/tegra/for-3.17-rc1' of git://anongit.freedesktop.org/tegra/linux: drm/tegra: add MODULE_DEVICE_TABLEs drm/tegra: dc - Reset controller on driver remove drm/tegra: Properly align stride for framebuffers drm/tegra: sor - Configure proper sync polarities drm/tegra: sor - Use bits-per-color from panel drm/tegra: Make job submission 64-bit safe drm/tegra: Allow non-authenticated processes to create buffer objects drm/tegra: Add SET/GET_FLAGS IOCTLs drm/tegra: Add SET/GET_TILING IOCTLs drm/tegra: Implement more tiling modes drm/tegra: dsi - Handle non-continuous clock flag drm/tegra: sor - missing unlock on error
This commit is contained in:
commit
fa1d0ee69c
@ -18,6 +18,8 @@
|
||||
struct tegra_dc_soc_info {
|
||||
bool supports_interlacing;
|
||||
bool supports_cursor;
|
||||
bool supports_block_linear;
|
||||
unsigned int pitch_align;
|
||||
};
|
||||
|
||||
struct tegra_plane {
|
||||
@ -212,15 +214,44 @@ static 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;
|
||||
}
|
||||
if (dc->soc->supports_block_linear) {
|
||||
unsigned long height = window->tiling.value;
|
||||
|
||||
tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
|
||||
switch (window->tiling.mode) {
|
||||
case TEGRA_BO_TILING_MODE_PITCH:
|
||||
value = DC_WINBUF_SURFACE_KIND_PITCH;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_TILED:
|
||||
value = DC_WINBUF_SURFACE_KIND_TILED;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_BLOCK:
|
||||
value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
|
||||
DC_WINBUF_SURFACE_KIND_BLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
|
||||
} else {
|
||||
switch (window->tiling.mode) {
|
||||
case TEGRA_BO_TILING_MODE_PITCH:
|
||||
value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
|
||||
DC_WIN_BUFFER_ADDR_MODE_LINEAR;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_TILED:
|
||||
value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
|
||||
DC_WIN_BUFFER_ADDR_MODE_TILE;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_BLOCK:
|
||||
DRM_ERROR("hardware doesn't support block linear mode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
|
||||
}
|
||||
|
||||
value = WIN_ENABLE;
|
||||
|
||||
@ -288,6 +319,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
struct tegra_dc *dc = to_tegra_dc(crtc);
|
||||
struct tegra_dc_window window;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
memset(&window, 0, sizeof(window));
|
||||
window.src.x = src_x >> 16;
|
||||
@ -301,7 +333,10 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
window.format = tegra_dc_format(fb->pixel_format, &window.swap);
|
||||
window.bits_per_pixel = fb->bits_per_pixel;
|
||||
window.bottom_up = tegra_fb_is_bottom_up(fb);
|
||||
window.tiled = tegra_fb_is_tiled(fb);
|
||||
|
||||
err = tegra_fb_get_tiling(fb, &window.tiling);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
|
||||
struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
|
||||
@ -402,8 +437,14 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
|
||||
{
|
||||
struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
|
||||
unsigned int h_offset = 0, v_offset = 0;
|
||||
struct tegra_bo_tiling tiling;
|
||||
unsigned int format, swap;
|
||||
unsigned long value;
|
||||
int err;
|
||||
|
||||
err = tegra_fb_get_tiling(fb, &tiling);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
|
||||
|
||||
@ -417,15 +458,44 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
|
||||
tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
|
||||
tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
|
||||
|
||||
if (tegra_fb_is_tiled(fb)) {
|
||||
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;
|
||||
}
|
||||
if (dc->soc->supports_block_linear) {
|
||||
unsigned long height = tiling.value;
|
||||
|
||||
tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
|
||||
switch (tiling.mode) {
|
||||
case TEGRA_BO_TILING_MODE_PITCH:
|
||||
value = DC_WINBUF_SURFACE_KIND_PITCH;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_TILED:
|
||||
value = DC_WINBUF_SURFACE_KIND_TILED;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_BLOCK:
|
||||
value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
|
||||
DC_WINBUF_SURFACE_KIND_BLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
|
||||
} else {
|
||||
switch (tiling.mode) {
|
||||
case TEGRA_BO_TILING_MODE_PITCH:
|
||||
value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
|
||||
DC_WIN_BUFFER_ADDR_MODE_LINEAR;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_TILED:
|
||||
value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
|
||||
DC_WIN_BUFFER_ADDR_MODE_TILE;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_BLOCK:
|
||||
DRM_ERROR("hardware doesn't support block linear mode\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
|
||||
}
|
||||
|
||||
/* make sure bottom-up buffers are properly displayed */
|
||||
if (tegra_fb_is_bottom_up(fb)) {
|
||||
@ -1214,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client)
|
||||
{
|
||||
struct drm_device *drm = dev_get_drvdata(client->parent);
|
||||
struct tegra_dc *dc = host1x_client_to_dc(client);
|
||||
struct tegra_drm *tegra = drm->dev_private;
|
||||
int err;
|
||||
|
||||
drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
|
||||
drm_mode_crtc_set_gamma_size(&dc->base, 256);
|
||||
drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
|
||||
|
||||
/*
|
||||
* Keep track of the minimum pitch alignment across all display
|
||||
* controllers.
|
||||
*/
|
||||
if (dc->soc->pitch_align > tegra->pitch_align)
|
||||
tegra->pitch_align = dc->soc->pitch_align;
|
||||
|
||||
err = tegra_dc_rgb_init(drm, dc);
|
||||
if (err < 0 && err != -ENODEV) {
|
||||
dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
|
||||
@ -1277,16 +1355,29 @@ static const struct host1x_client_ops dc_client_ops = {
|
||||
static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
|
||||
.supports_interlacing = false,
|
||||
.supports_cursor = false,
|
||||
.supports_block_linear = false,
|
||||
.pitch_align = 8,
|
||||
};
|
||||
|
||||
static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
|
||||
.supports_interlacing = false,
|
||||
.supports_cursor = false,
|
||||
.supports_block_linear = false,
|
||||
.pitch_align = 8,
|
||||
};
|
||||
|
||||
static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
|
||||
.supports_interlacing = false,
|
||||
.supports_cursor = false,
|
||||
.supports_block_linear = false,
|
||||
.pitch_align = 64,
|
||||
};
|
||||
|
||||
static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
|
||||
.supports_interlacing = true,
|
||||
.supports_cursor = true,
|
||||
.supports_block_linear = true,
|
||||
.pitch_align = 64,
|
||||
};
|
||||
|
||||
static const struct of_device_id tegra_dc_of_match[] = {
|
||||
@ -1303,6 +1394,7 @@ static const struct of_device_id tegra_dc_of_match[] = {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
|
||||
|
||||
static int tegra_dc_parse_dt(struct tegra_dc *dc)
|
||||
{
|
||||
@ -1430,6 +1522,7 @@ static int tegra_dc_remove(struct platform_device *pdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
reset_control_assert(dc->rst);
|
||||
clk_disable_unprepare(dc->clk);
|
||||
|
||||
return 0;
|
||||
|
@ -428,6 +428,11 @@
|
||||
#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809
|
||||
|
||||
#define DC_WINBUF_UFLOW_STATUS 0x80a
|
||||
#define DC_WINBUF_SURFACE_KIND 0x80b
|
||||
#define DC_WINBUF_SURFACE_KIND_PITCH (0 << 0)
|
||||
#define DC_WINBUF_SURFACE_KIND_TILED (1 << 0)
|
||||
#define DC_WINBUF_SURFACE_KIND_BLOCK (2 << 0)
|
||||
#define DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
|
||||
|
||||
#define DC_WINBUF_AD_UFLOW_STATUS 0xbca
|
||||
#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
|
||||
|
@ -382,6 +382,7 @@ static const struct of_device_id tegra_dpaux_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra124-dpaux", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
|
||||
|
||||
struct platform_driver tegra_dpaux_driver = {
|
||||
.driver = {
|
||||
|
@ -132,6 +132,45 @@ host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle)
|
||||
return &bo->base;
|
||||
}
|
||||
|
||||
static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
|
||||
struct drm_tegra_reloc __user *src,
|
||||
struct drm_device *drm,
|
||||
struct drm_file *file)
|
||||
{
|
||||
u32 cmdbuf, target;
|
||||
int err;
|
||||
|
||||
err = get_user(cmdbuf, &src->cmdbuf.handle);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = get_user(dest->cmdbuf.offset, &src->cmdbuf.offset);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = get_user(target, &src->target.handle);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = get_user(dest->target.offset, &src->cmdbuf.offset);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = get_user(dest->shift, &src->shift);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
dest->cmdbuf.bo = host1x_bo_lookup(drm, file, cmdbuf);
|
||||
if (!dest->cmdbuf.bo)
|
||||
return -ENOENT;
|
||||
|
||||
dest->target.bo = host1x_bo_lookup(drm, file, target);
|
||||
if (!dest->target.bo)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tegra_drm_submit(struct tegra_drm_context *context,
|
||||
struct drm_tegra_submit *args, struct drm_device *drm,
|
||||
struct drm_file *file)
|
||||
@ -184,26 +223,13 @@ int tegra_drm_submit(struct tegra_drm_context *context,
|
||||
cmdbufs++;
|
||||
}
|
||||
|
||||
if (copy_from_user(job->relocarray, relocs,
|
||||
sizeof(*relocs) * num_relocs)) {
|
||||
err = -EFAULT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* copy and resolve relocations from submit */
|
||||
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) {
|
||||
err = -ENOENT;
|
||||
err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs],
|
||||
&relocs[num_relocs], drm,
|
||||
file);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_from_user(job->waitchk, waitchks,
|
||||
@ -455,11 +481,151 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct drm_tegra_gem_set_tiling *args = data;
|
||||
enum tegra_bo_tiling_mode mode;
|
||||
struct drm_gem_object *gem;
|
||||
unsigned long value = 0;
|
||||
struct tegra_bo *bo;
|
||||
|
||||
switch (args->mode) {
|
||||
case DRM_TEGRA_GEM_TILING_MODE_PITCH:
|
||||
mode = TEGRA_BO_TILING_MODE_PITCH;
|
||||
|
||||
if (args->value != 0)
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
|
||||
case DRM_TEGRA_GEM_TILING_MODE_TILED:
|
||||
mode = TEGRA_BO_TILING_MODE_TILED;
|
||||
|
||||
if (args->value != 0)
|
||||
return -EINVAL;
|
||||
|
||||
break;
|
||||
|
||||
case DRM_TEGRA_GEM_TILING_MODE_BLOCK:
|
||||
mode = TEGRA_BO_TILING_MODE_BLOCK;
|
||||
|
||||
if (args->value > 5)
|
||||
return -EINVAL;
|
||||
|
||||
value = args->value;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
gem = drm_gem_object_lookup(drm, file, args->handle);
|
||||
if (!gem)
|
||||
return -ENOENT;
|
||||
|
||||
bo = to_tegra_bo(gem);
|
||||
|
||||
bo->tiling.mode = mode;
|
||||
bo->tiling.value = value;
|
||||
|
||||
drm_gem_object_unreference(gem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct drm_tegra_gem_get_tiling *args = data;
|
||||
struct drm_gem_object *gem;
|
||||
struct tegra_bo *bo;
|
||||
int err = 0;
|
||||
|
||||
gem = drm_gem_object_lookup(drm, file, args->handle);
|
||||
if (!gem)
|
||||
return -ENOENT;
|
||||
|
||||
bo = to_tegra_bo(gem);
|
||||
|
||||
switch (bo->tiling.mode) {
|
||||
case TEGRA_BO_TILING_MODE_PITCH:
|
||||
args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
|
||||
args->value = 0;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_TILED:
|
||||
args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED;
|
||||
args->value = 0;
|
||||
break;
|
||||
|
||||
case TEGRA_BO_TILING_MODE_BLOCK:
|
||||
args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
|
||||
args->value = bo->tiling.value;
|
||||
break;
|
||||
|
||||
default:
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
drm_gem_object_unreference(gem);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int tegra_gem_set_flags(struct drm_device *drm, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct drm_tegra_gem_set_flags *args = data;
|
||||
struct drm_gem_object *gem;
|
||||
struct tegra_bo *bo;
|
||||
|
||||
if (args->flags & ~DRM_TEGRA_GEM_FLAGS)
|
||||
return -EINVAL;
|
||||
|
||||
gem = drm_gem_object_lookup(drm, file, args->handle);
|
||||
if (!gem)
|
||||
return -ENOENT;
|
||||
|
||||
bo = to_tegra_bo(gem);
|
||||
bo->flags = 0;
|
||||
|
||||
if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
|
||||
bo->flags |= TEGRA_BO_BOTTOM_UP;
|
||||
|
||||
drm_gem_object_unreference(gem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gem_get_flags(struct drm_device *drm, void *data,
|
||||
struct drm_file *file)
|
||||
{
|
||||
struct drm_tegra_gem_get_flags *args = data;
|
||||
struct drm_gem_object *gem;
|
||||
struct tegra_bo *bo;
|
||||
|
||||
gem = drm_gem_object_lookup(drm, file, args->handle);
|
||||
if (!gem)
|
||||
return -ENOENT;
|
||||
|
||||
bo = to_tegra_bo(gem);
|
||||
args->flags = 0;
|
||||
|
||||
if (bo->flags & TEGRA_BO_BOTTOM_UP)
|
||||
args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
|
||||
|
||||
drm_gem_object_unreference(gem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
|
||||
#ifdef CONFIG_DRM_TEGRA_STAGING
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
|
||||
@ -469,6 +635,10 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED),
|
||||
DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED),
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fixed.h>
|
||||
|
||||
#include "gem.h"
|
||||
|
||||
struct reset_control;
|
||||
|
||||
struct tegra_fb {
|
||||
@ -43,6 +45,8 @@ struct tegra_drm {
|
||||
#ifdef CONFIG_DRM_TEGRA_FBDEV
|
||||
struct tegra_fbdev *fbdev;
|
||||
#endif
|
||||
|
||||
unsigned int pitch_align;
|
||||
};
|
||||
|
||||
struct tegra_drm_client;
|
||||
@ -160,7 +164,8 @@ struct tegra_dc_window {
|
||||
unsigned int stride[2];
|
||||
unsigned long base[3];
|
||||
bool bottom_up;
|
||||
bool tiled;
|
||||
|
||||
struct tegra_bo_tiling tiling;
|
||||
};
|
||||
|
||||
/* from dc.c */
|
||||
@ -279,7 +284,8 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
|
||||
struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
|
||||
unsigned int index);
|
||||
bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
|
||||
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer);
|
||||
int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
|
||||
struct tegra_bo_tiling *tiling);
|
||||
int tegra_drm_fb_prepare(struct drm_device *drm);
|
||||
int tegra_drm_fb_init(struct drm_device *drm);
|
||||
void tegra_drm_fb_exit(struct drm_device *drm);
|
||||
|
@ -474,7 +474,8 @@ static int tegra_output_dsi_enable(struct tegra_output *output)
|
||||
tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
|
||||
|
||||
value = tegra_dsi_readl(dsi, DSI_CONTROL);
|
||||
value |= DSI_CONTROL_HS_CLK_CTRL;
|
||||
if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
|
||||
value |= DSI_CONTROL_HS_CLK_CTRL;
|
||||
value &= ~DSI_CONTROL_TX_TRIG(3);
|
||||
value &= ~DSI_CONTROL_DCS_ENABLE;
|
||||
value |= DSI_CONTROL_VIDEO_ENABLE;
|
||||
@ -982,6 +983,7 @@ static const struct of_device_id tegra_dsi_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra114-dsi", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
|
||||
|
||||
struct platform_driver tegra_dsi_driver = {
|
||||
.driver = {
|
||||
|
@ -46,14 +46,15 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer)
|
||||
int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
|
||||
struct tegra_bo_tiling *tiling)
|
||||
{
|
||||
struct tegra_fb *fb = to_tegra_fb(framebuffer);
|
||||
|
||||
if (fb->planes[0]->flags & TEGRA_BO_TILED)
|
||||
return true;
|
||||
/* TODO: handle YUV formats? */
|
||||
*tiling = fb->planes[0]->tiling;
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
|
||||
@ -193,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct tegra_fbdev *fbdev = to_tegra_fbdev(helper);
|
||||
struct tegra_drm *tegra = helper->dev->dev_private;
|
||||
struct drm_device *drm = helper->dev;
|
||||
struct drm_mode_fb_cmd2 cmd = { 0 };
|
||||
unsigned int bytes_per_pixel;
|
||||
@ -207,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
|
||||
|
||||
cmd.width = sizes->surface_width;
|
||||
cmd.height = sizes->surface_height;
|
||||
cmd.pitches[0] = sizes->surface_width * bytes_per_pixel;
|
||||
cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel,
|
||||
tegra->pitch_align);
|
||||
cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
|
||||
sizes->surface_depth);
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <linux/dma-buf.h>
|
||||
#include <drm/tegra_drm.h>
|
||||
|
||||
#include "drm.h"
|
||||
#include "gem.h"
|
||||
|
||||
static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
|
||||
@ -126,7 +127,7 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
|
||||
goto err_mmap;
|
||||
|
||||
if (flags & DRM_TEGRA_GEM_CREATE_TILED)
|
||||
bo->flags |= TEGRA_BO_TILED;
|
||||
bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED;
|
||||
|
||||
if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP)
|
||||
bo->flags |= TEGRA_BO_BOTTOM_UP;
|
||||
@ -259,8 +260,10 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
|
||||
struct tegra_drm *tegra = drm->dev_private;
|
||||
struct tegra_bo *bo;
|
||||
|
||||
min_pitch = round_up(min_pitch, tegra->pitch_align);
|
||||
if (args->pitch < min_pitch)
|
||||
args->pitch = min_pitch;
|
||||
|
||||
|
@ -16,8 +16,18 @@
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drmP.h>
|
||||
|
||||
#define TEGRA_BO_TILED (1 << 0)
|
||||
#define TEGRA_BO_BOTTOM_UP (1 << 1)
|
||||
#define TEGRA_BO_BOTTOM_UP (1 << 0)
|
||||
|
||||
enum tegra_bo_tiling_mode {
|
||||
TEGRA_BO_TILING_MODE_PITCH,
|
||||
TEGRA_BO_TILING_MODE_TILED,
|
||||
TEGRA_BO_TILING_MODE_BLOCK,
|
||||
};
|
||||
|
||||
struct tegra_bo_tiling {
|
||||
enum tegra_bo_tiling_mode mode;
|
||||
unsigned long value;
|
||||
};
|
||||
|
||||
struct tegra_bo {
|
||||
struct drm_gem_object gem;
|
||||
@ -26,6 +36,8 @@ struct tegra_bo {
|
||||
struct sg_table *sgt;
|
||||
dma_addr_t paddr;
|
||||
void *vaddr;
|
||||
|
||||
struct tegra_bo_tiling tiling;
|
||||
};
|
||||
|
||||
static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
|
||||
|
@ -121,6 +121,7 @@ static const struct of_device_id gr2d_match[] = {
|
||||
{ .compatible = "nvidia,tegra20-gr2d" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, gr2d_match);
|
||||
|
||||
static const u32 gr2d_addr_regs[] = {
|
||||
GR2D_UA_BASE_ADDR,
|
||||
|
@ -130,6 +130,7 @@ static const struct of_device_id tegra_gr3d_match[] = {
|
||||
{ .compatible = "nvidia,tegra20-gr3d" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_gr3d_match);
|
||||
|
||||
static const u32 gr3d_addr_regs[] = {
|
||||
GR3D_IDX_ATTRIBUTE( 0),
|
||||
|
@ -1450,6 +1450,7 @@ static const struct of_device_id tegra_hdmi_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_hdmi_of_match);
|
||||
|
||||
static int tegra_hdmi_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
@ -516,7 +516,7 @@ static int tegra_output_sor_enable(struct tegra_output *output)
|
||||
if (err < 0) {
|
||||
dev_err(sor->dev, "failed to probe eDP link: %d\n",
|
||||
err);
|
||||
return err;
|
||||
goto unlock;
|
||||
}
|
||||
}
|
||||
|
||||
@ -525,7 +525,7 @@ static int tegra_output_sor_enable(struct tegra_output *output)
|
||||
dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.bits_per_pixel = 24; /* XXX: don't hardcode? */
|
||||
config.bits_per_pixel = output->connector.display_info.bpc * 3;
|
||||
|
||||
err = tegra_sor_calc_config(sor, mode, &config, &link);
|
||||
if (err < 0)
|
||||
@ -815,12 +815,22 @@ static int tegra_output_sor_enable(struct tegra_output *output)
|
||||
* configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
|
||||
* raster, associate with display controller)
|
||||
*/
|
||||
value = SOR_STATE_ASY_VSYNCPOL |
|
||||
SOR_STATE_ASY_HSYNCPOL |
|
||||
SOR_STATE_ASY_PROTOCOL_DP_A |
|
||||
value = SOR_STATE_ASY_PROTOCOL_DP_A |
|
||||
SOR_STATE_ASY_CRC_MODE_COMPLETE |
|
||||
SOR_STATE_ASY_OWNER(dc->pipe + 1);
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PHSYNC)
|
||||
value &= ~SOR_STATE_ASY_HSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
value |= SOR_STATE_ASY_HSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
value &= ~SOR_STATE_ASY_VSYNCPOL;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
value |= SOR_STATE_ASY_VSYNCPOL;
|
||||
|
||||
switch (config.bits_per_pixel) {
|
||||
case 24:
|
||||
value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
|
||||
@ -1455,6 +1465,7 @@ static const struct of_device_id tegra_sor_of_match[] = {
|
||||
{ .compatible = "nvidia,tegra124-sor", },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
|
||||
|
||||
struct platform_driver tegra_sor_driver = {
|
||||
.driver = {
|
||||
|
@ -185,16 +185,16 @@ static unsigned int pin_job(struct host1x_job *job)
|
||||
struct sg_table *sgt;
|
||||
dma_addr_t phys_addr;
|
||||
|
||||
reloc->target = host1x_bo_get(reloc->target);
|
||||
if (!reloc->target)
|
||||
reloc->target.bo = host1x_bo_get(reloc->target.bo);
|
||||
if (!reloc->target.bo)
|
||||
goto unpin;
|
||||
|
||||
phys_addr = host1x_bo_pin(reloc->target, &sgt);
|
||||
phys_addr = host1x_bo_pin(reloc->target.bo, &sgt);
|
||||
if (!phys_addr)
|
||||
goto unpin;
|
||||
|
||||
job->addr_phys[job->num_unpins] = phys_addr;
|
||||
job->unpins[job->num_unpins].bo = reloc->target;
|
||||
job->unpins[job->num_unpins].bo = reloc->target.bo;
|
||||
job->unpins[job->num_unpins].sgt = sgt;
|
||||
job->num_unpins++;
|
||||
}
|
||||
@ -235,21 +235,21 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
|
||||
for (i = 0; i < job->num_relocs; i++) {
|
||||
struct host1x_reloc *reloc = &job->relocarray[i];
|
||||
u32 reloc_addr = (job->reloc_addr_phys[i] +
|
||||
reloc->target_offset) >> reloc->shift;
|
||||
reloc->target.offset) >> reloc->shift;
|
||||
u32 *target;
|
||||
|
||||
/* skip all other gathers */
|
||||
if (cmdbuf != reloc->cmdbuf)
|
||||
if (cmdbuf != reloc->cmdbuf.bo)
|
||||
continue;
|
||||
|
||||
if (last_page != reloc->cmdbuf_offset >> PAGE_SHIFT) {
|
||||
if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
|
||||
if (cmdbuf_page_addr)
|
||||
host1x_bo_kunmap(cmdbuf, last_page,
|
||||
cmdbuf_page_addr);
|
||||
|
||||
cmdbuf_page_addr = host1x_bo_kmap(cmdbuf,
|
||||
reloc->cmdbuf_offset >> PAGE_SHIFT);
|
||||
last_page = reloc->cmdbuf_offset >> PAGE_SHIFT;
|
||||
reloc->cmdbuf.offset >> PAGE_SHIFT);
|
||||
last_page = reloc->cmdbuf.offset >> PAGE_SHIFT;
|
||||
|
||||
if (unlikely(!cmdbuf_page_addr)) {
|
||||
pr_err("Could not map cmdbuf for relocation\n");
|
||||
@ -257,7 +257,7 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
|
||||
}
|
||||
}
|
||||
|
||||
target = cmdbuf_page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK);
|
||||
target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK);
|
||||
*target = reloc_addr;
|
||||
}
|
||||
|
||||
@ -272,7 +272,7 @@ static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf,
|
||||
{
|
||||
offset *= sizeof(u32);
|
||||
|
||||
if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset)
|
||||
if (reloc->cmdbuf.bo != cmdbuf || reloc->cmdbuf.offset != offset)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -164,12 +164,15 @@ int host1x_job_submit(struct host1x_job *job);
|
||||
*/
|
||||
|
||||
struct host1x_reloc {
|
||||
struct host1x_bo *cmdbuf;
|
||||
u32 cmdbuf_offset;
|
||||
struct host1x_bo *target;
|
||||
u32 target_offset;
|
||||
u32 shift;
|
||||
u32 pad;
|
||||
struct {
|
||||
struct host1x_bo *bo;
|
||||
unsigned long offset;
|
||||
} cmdbuf;
|
||||
struct {
|
||||
struct host1x_bo *bo;
|
||||
unsigned long offset;
|
||||
} target;
|
||||
unsigned long shift;
|
||||
};
|
||||
|
||||
struct host1x_job {
|
||||
|
@ -129,6 +129,44 @@ struct drm_tegra_submit {
|
||||
__u32 reserved[5]; /* future expansion */
|
||||
};
|
||||
|
||||
#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0
|
||||
#define DRM_TEGRA_GEM_TILING_MODE_TILED 1
|
||||
#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2
|
||||
|
||||
struct drm_tegra_gem_set_tiling {
|
||||
/* input */
|
||||
__u32 handle;
|
||||
__u32 mode;
|
||||
__u32 value;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
struct drm_tegra_gem_get_tiling {
|
||||
/* input */
|
||||
__u32 handle;
|
||||
/* output */
|
||||
__u32 mode;
|
||||
__u32 value;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0)
|
||||
#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP)
|
||||
|
||||
struct drm_tegra_gem_set_flags {
|
||||
/* input */
|
||||
__u32 handle;
|
||||
/* output */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
struct drm_tegra_gem_get_flags {
|
||||
/* input */
|
||||
__u32 handle;
|
||||
/* output */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
#define DRM_TEGRA_GEM_CREATE 0x00
|
||||
#define DRM_TEGRA_GEM_MMAP 0x01
|
||||
#define DRM_TEGRA_SYNCPT_READ 0x02
|
||||
@ -139,6 +177,10 @@ struct drm_tegra_submit {
|
||||
#define DRM_TEGRA_GET_SYNCPT 0x07
|
||||
#define DRM_TEGRA_SUBMIT 0x08
|
||||
#define DRM_TEGRA_GET_SYNCPT_BASE 0x09
|
||||
#define DRM_TEGRA_GEM_SET_TILING 0x0a
|
||||
#define DRM_TEGRA_GEM_GET_TILING 0x0b
|
||||
#define DRM_TEGRA_GEM_SET_FLAGS 0x0c
|
||||
#define DRM_TEGRA_GEM_GET_FLAGS 0x0d
|
||||
|
||||
#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
|
||||
#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
|
||||
@ -150,5 +192,9 @@ struct drm_tegra_submit {
|
||||
#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt)
|
||||
#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
|
||||
#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
|
||||
#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling)
|
||||
#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
|
||||
#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags)
|
||||
#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags)
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user