diff options
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 123 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dpaux.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.c | 208 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dsi.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/fb.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gr2d.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gr3d.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/hdmi.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 21 | ||||
-rw-r--r-- | drivers/gpu/host1x/job.c | 22 | ||||
-rw-r--r-- | include/linux/host1x.h | 15 | ||||
-rw-r--r-- | include/uapi/drm/tegra_drm.h | 46 |
16 files changed, 425 insertions, 67 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index ef40381f3909..6553fd238685 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -18,6 +18,8 @@ | |||
18 | struct tegra_dc_soc_info { | 18 | struct tegra_dc_soc_info { |
19 | bool supports_interlacing; | 19 | bool supports_interlacing; |
20 | bool supports_cursor; | 20 | bool supports_cursor; |
21 | bool supports_block_linear; | ||
22 | unsigned int pitch_align; | ||
21 | }; | 23 | }; |
22 | 24 | ||
23 | struct tegra_plane { | 25 | struct tegra_plane { |
@@ -212,15 +214,44 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index, | |||
212 | tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); | 214 | tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); |
213 | tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); | 215 | tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); |
214 | 216 | ||
215 | if (window->tiled) { | 217 | if (dc->soc->supports_block_linear) { |
216 | value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | | 218 | unsigned long height = window->tiling.value; |
217 | DC_WIN_BUFFER_ADDR_MODE_TILE; | 219 | |
220 | switch (window->tiling.mode) { | ||
221 | case TEGRA_BO_TILING_MODE_PITCH: | ||
222 | value = DC_WINBUF_SURFACE_KIND_PITCH; | ||
223 | break; | ||
224 | |||
225 | case TEGRA_BO_TILING_MODE_TILED: | ||
226 | value = DC_WINBUF_SURFACE_KIND_TILED; | ||
227 | break; | ||
228 | |||
229 | case TEGRA_BO_TILING_MODE_BLOCK: | ||
230 | value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) | | ||
231 | DC_WINBUF_SURFACE_KIND_BLOCK; | ||
232 | break; | ||
233 | } | ||
234 | |||
235 | tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND); | ||
218 | } else { | 236 | } else { |
219 | value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | | 237 | switch (window->tiling.mode) { |
220 | DC_WIN_BUFFER_ADDR_MODE_LINEAR; | 238 | case TEGRA_BO_TILING_MODE_PITCH: |
221 | } | 239 | value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | |
240 | DC_WIN_BUFFER_ADDR_MODE_LINEAR; | ||
241 | break; | ||
222 | 242 | ||
223 | tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); | 243 | case TEGRA_BO_TILING_MODE_TILED: |
244 | value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | | ||
245 | DC_WIN_BUFFER_ADDR_MODE_TILE; | ||
246 | break; | ||
247 | |||
248 | case TEGRA_BO_TILING_MODE_BLOCK: | ||
249 | DRM_ERROR("hardware doesn't support block linear mode\n"); | ||
250 | return -EINVAL; | ||
251 | } | ||
252 | |||
253 | tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); | ||
254 | } | ||
224 | 255 | ||
225 | value = WIN_ENABLE; | 256 | value = WIN_ENABLE; |
226 | 257 | ||
@@ -288,6 +319,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
288 | struct tegra_dc *dc = to_tegra_dc(crtc); | 319 | struct tegra_dc *dc = to_tegra_dc(crtc); |
289 | struct tegra_dc_window window; | 320 | struct tegra_dc_window window; |
290 | unsigned int i; | 321 | unsigned int i; |
322 | int err; | ||
291 | 323 | ||
292 | memset(&window, 0, sizeof(window)); | 324 | memset(&window, 0, sizeof(window)); |
293 | window.src.x = src_x >> 16; | 325 | window.src.x = src_x >> 16; |
@@ -301,7 +333,10 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, | |||
301 | window.format = tegra_dc_format(fb->pixel_format, &window.swap); | 333 | window.format = tegra_dc_format(fb->pixel_format, &window.swap); |
302 | window.bits_per_pixel = fb->bits_per_pixel; | 334 | window.bits_per_pixel = fb->bits_per_pixel; |
303 | window.bottom_up = tegra_fb_is_bottom_up(fb); | 335 | window.bottom_up = tegra_fb_is_bottom_up(fb); |
304 | window.tiled = tegra_fb_is_tiled(fb); | 336 | |
337 | err = tegra_fb_get_tiling(fb, &window.tiling); | ||
338 | if (err < 0) | ||
339 | return err; | ||
305 | 340 | ||
306 | for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { | 341 | for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { |
307 | struct tegra_bo *bo = tegra_fb_get_plane(fb, i); | 342 | 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, | |||
402 | { | 437 | { |
403 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); | 438 | struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); |
404 | unsigned int h_offset = 0, v_offset = 0; | 439 | unsigned int h_offset = 0, v_offset = 0; |
440 | struct tegra_bo_tiling tiling; | ||
405 | unsigned int format, swap; | 441 | unsigned int format, swap; |
406 | unsigned long value; | 442 | unsigned long value; |
443 | int err; | ||
444 | |||
445 | err = tegra_fb_get_tiling(fb, &tiling); | ||
446 | if (err < 0) | ||
447 | return err; | ||
407 | 448 | ||
408 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); | 449 | tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); |
409 | 450 | ||
@@ -417,15 +458,44 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y, | |||
417 | tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); | 458 | tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); |
418 | tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP); | 459 | tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP); |
419 | 460 | ||
420 | if (tegra_fb_is_tiled(fb)) { | 461 | if (dc->soc->supports_block_linear) { |
421 | value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | | 462 | unsigned long height = tiling.value; |
422 | DC_WIN_BUFFER_ADDR_MODE_TILE; | 463 | |
464 | switch (tiling.mode) { | ||
465 | case TEGRA_BO_TILING_MODE_PITCH: | ||
466 | value = DC_WINBUF_SURFACE_KIND_PITCH; | ||
467 | break; | ||
468 | |||
469 | case TEGRA_BO_TILING_MODE_TILED: | ||
470 | value = DC_WINBUF_SURFACE_KIND_TILED; | ||
471 | break; | ||
472 | |||
473 | case TEGRA_BO_TILING_MODE_BLOCK: | ||
474 | value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) | | ||
475 | DC_WINBUF_SURFACE_KIND_BLOCK; | ||
476 | break; | ||
477 | } | ||
478 | |||
479 | tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND); | ||
423 | } else { | 480 | } else { |
424 | value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | | 481 | switch (tiling.mode) { |
425 | DC_WIN_BUFFER_ADDR_MODE_LINEAR; | 482 | case TEGRA_BO_TILING_MODE_PITCH: |
426 | } | 483 | value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | |
484 | DC_WIN_BUFFER_ADDR_MODE_LINEAR; | ||
485 | break; | ||
486 | |||
487 | case TEGRA_BO_TILING_MODE_TILED: | ||
488 | value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | | ||
489 | DC_WIN_BUFFER_ADDR_MODE_TILE; | ||
490 | break; | ||
491 | |||
492 | case TEGRA_BO_TILING_MODE_BLOCK: | ||
493 | DRM_ERROR("hardware doesn't support block linear mode\n"); | ||
494 | return -EINVAL; | ||
495 | } | ||
427 | 496 | ||
428 | tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); | 497 | tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); |
498 | } | ||
429 | 499 | ||
430 | /* make sure bottom-up buffers are properly displayed */ | 500 | /* make sure bottom-up buffers are properly displayed */ |
431 | if (tegra_fb_is_bottom_up(fb)) { | 501 | if (tegra_fb_is_bottom_up(fb)) { |
@@ -1214,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client) | |||
1214 | { | 1284 | { |
1215 | struct drm_device *drm = dev_get_drvdata(client->parent); | 1285 | struct drm_device *drm = dev_get_drvdata(client->parent); |
1216 | struct tegra_dc *dc = host1x_client_to_dc(client); | 1286 | struct tegra_dc *dc = host1x_client_to_dc(client); |
1287 | struct tegra_drm *tegra = drm->dev_private; | ||
1217 | int err; | 1288 | int err; |
1218 | 1289 | ||
1219 | drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); | 1290 | drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); |
1220 | drm_mode_crtc_set_gamma_size(&dc->base, 256); | 1291 | drm_mode_crtc_set_gamma_size(&dc->base, 256); |
1221 | drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); | 1292 | drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); |
1222 | 1293 | ||
1294 | /* | ||
1295 | * Keep track of the minimum pitch alignment across all display | ||
1296 | * controllers. | ||
1297 | */ | ||
1298 | if (dc->soc->pitch_align > tegra->pitch_align) | ||
1299 | tegra->pitch_align = dc->soc->pitch_align; | ||
1300 | |||
1223 | err = tegra_dc_rgb_init(drm, dc); | 1301 | err = tegra_dc_rgb_init(drm, dc); |
1224 | if (err < 0 && err != -ENODEV) { | 1302 | if (err < 0 && err != -ENODEV) { |
1225 | dev_err(dc->dev, "failed to initialize RGB output: %d\n", err); | 1303 | 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 = { | |||
1277 | static const struct tegra_dc_soc_info tegra20_dc_soc_info = { | 1355 | static const struct tegra_dc_soc_info tegra20_dc_soc_info = { |
1278 | .supports_interlacing = false, | 1356 | .supports_interlacing = false, |
1279 | .supports_cursor = false, | 1357 | .supports_cursor = false, |
1358 | .supports_block_linear = false, | ||
1359 | .pitch_align = 8, | ||
1280 | }; | 1360 | }; |
1281 | 1361 | ||
1282 | static const struct tegra_dc_soc_info tegra30_dc_soc_info = { | 1362 | static const struct tegra_dc_soc_info tegra30_dc_soc_info = { |
1283 | .supports_interlacing = false, | 1363 | .supports_interlacing = false, |
1284 | .supports_cursor = false, | 1364 | .supports_cursor = false, |
1365 | .supports_block_linear = false, | ||
1366 | .pitch_align = 8, | ||
1367 | }; | ||
1368 | |||
1369 | static const struct tegra_dc_soc_info tegra114_dc_soc_info = { | ||
1370 | .supports_interlacing = false, | ||
1371 | .supports_cursor = false, | ||
1372 | .supports_block_linear = false, | ||
1373 | .pitch_align = 64, | ||
1285 | }; | 1374 | }; |
1286 | 1375 | ||
1287 | static const struct tegra_dc_soc_info tegra124_dc_soc_info = { | 1376 | static const struct tegra_dc_soc_info tegra124_dc_soc_info = { |
1288 | .supports_interlacing = true, | 1377 | .supports_interlacing = true, |
1289 | .supports_cursor = true, | 1378 | .supports_cursor = true, |
1379 | .supports_block_linear = true, | ||
1380 | .pitch_align = 64, | ||
1290 | }; | 1381 | }; |
1291 | 1382 | ||
1292 | static const struct of_device_id tegra_dc_of_match[] = { | 1383 | static const struct of_device_id tegra_dc_of_match[] = { |
@@ -1303,6 +1394,7 @@ static const struct of_device_id tegra_dc_of_match[] = { | |||
1303 | /* sentinel */ | 1394 | /* sentinel */ |
1304 | } | 1395 | } |
1305 | }; | 1396 | }; |
1397 | MODULE_DEVICE_TABLE(of, tegra_dc_of_match); | ||
1306 | 1398 | ||
1307 | static int tegra_dc_parse_dt(struct tegra_dc *dc) | 1399 | static int tegra_dc_parse_dt(struct tegra_dc *dc) |
1308 | { | 1400 | { |
@@ -1430,6 +1522,7 @@ static int tegra_dc_remove(struct platform_device *pdev) | |||
1430 | return err; | 1522 | return err; |
1431 | } | 1523 | } |
1432 | 1524 | ||
1525 | reset_control_assert(dc->rst); | ||
1433 | clk_disable_unprepare(dc->clk); | 1526 | clk_disable_unprepare(dc->clk); |
1434 | 1527 | ||
1435 | return 0; | 1528 | return 0; |
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 78c5feff95d2..705c93b00794 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h | |||
@@ -428,6 +428,11 @@ | |||
428 | #define DC_WINBUF_ADDR_V_OFFSET_NS 0x809 | 428 | #define DC_WINBUF_ADDR_V_OFFSET_NS 0x809 |
429 | 429 | ||
430 | #define DC_WINBUF_UFLOW_STATUS 0x80a | 430 | #define DC_WINBUF_UFLOW_STATUS 0x80a |
431 | #define DC_WINBUF_SURFACE_KIND 0x80b | ||
432 | #define DC_WINBUF_SURFACE_KIND_PITCH (0 << 0) | ||
433 | #define DC_WINBUF_SURFACE_KIND_TILED (1 << 0) | ||
434 | #define DC_WINBUF_SURFACE_KIND_BLOCK (2 << 0) | ||
435 | #define DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4) | ||
431 | 436 | ||
432 | #define DC_WINBUF_AD_UFLOW_STATUS 0xbca | 437 | #define DC_WINBUF_AD_UFLOW_STATUS 0xbca |
433 | #define DC_WINBUF_BD_UFLOW_STATUS 0xdca | 438 | #define DC_WINBUF_BD_UFLOW_STATUS 0xdca |
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 3f132e356e9c..708f783ead47 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c | |||
@@ -382,6 +382,7 @@ static const struct of_device_id tegra_dpaux_of_match[] = { | |||
382 | { .compatible = "nvidia,tegra124-dpaux", }, | 382 | { .compatible = "nvidia,tegra124-dpaux", }, |
383 | { }, | 383 | { }, |
384 | }; | 384 | }; |
385 | MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match); | ||
385 | 386 | ||
386 | struct platform_driver tegra_dpaux_driver = { | 387 | struct platform_driver tegra_dpaux_driver = { |
387 | .driver = { | 388 | .driver = { |
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index fd736efd14bd..59736bb810cd 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
@@ -132,6 +132,45 @@ host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle) | |||
132 | return &bo->base; | 132 | return &bo->base; |
133 | } | 133 | } |
134 | 134 | ||
135 | static int host1x_reloc_copy_from_user(struct host1x_reloc *dest, | ||
136 | struct drm_tegra_reloc __user *src, | ||
137 | struct drm_device *drm, | ||
138 | struct drm_file *file) | ||
139 | { | ||
140 | u32 cmdbuf, target; | ||
141 | int err; | ||
142 | |||
143 | err = get_user(cmdbuf, &src->cmdbuf.handle); | ||
144 | if (err < 0) | ||
145 | return err; | ||
146 | |||
147 | err = get_user(dest->cmdbuf.offset, &src->cmdbuf.offset); | ||
148 | if (err < 0) | ||
149 | return err; | ||
150 | |||
151 | err = get_user(target, &src->target.handle); | ||
152 | if (err < 0) | ||
153 | return err; | ||
154 | |||
155 | err = get_user(dest->target.offset, &src->cmdbuf.offset); | ||
156 | if (err < 0) | ||
157 | return err; | ||
158 | |||
159 | err = get_user(dest->shift, &src->shift); | ||
160 | if (err < 0) | ||
161 | return err; | ||
162 | |||
163 | dest->cmdbuf.bo = host1x_bo_lookup(drm, file, cmdbuf); | ||
164 | if (!dest->cmdbuf.bo) | ||
165 | return -ENOENT; | ||
166 | |||
167 | dest->target.bo = host1x_bo_lookup(drm, file, target); | ||
168 | if (!dest->target.bo) | ||
169 | return -ENOENT; | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
135 | int tegra_drm_submit(struct tegra_drm_context *context, | 174 | int tegra_drm_submit(struct tegra_drm_context *context, |
136 | struct drm_tegra_submit *args, struct drm_device *drm, | 175 | struct drm_tegra_submit *args, struct drm_device *drm, |
137 | struct drm_file *file) | 176 | struct drm_file *file) |
@@ -184,26 +223,13 @@ int tegra_drm_submit(struct tegra_drm_context *context, | |||
184 | cmdbufs++; | 223 | cmdbufs++; |
185 | } | 224 | } |
186 | 225 | ||
187 | if (copy_from_user(job->relocarray, relocs, | 226 | /* copy and resolve relocations from submit */ |
188 | sizeof(*relocs) * num_relocs)) { | ||
189 | err = -EFAULT; | ||
190 | goto fail; | ||
191 | } | ||
192 | |||
193 | while (num_relocs--) { | 227 | while (num_relocs--) { |
194 | struct host1x_reloc *reloc = &job->relocarray[num_relocs]; | 228 | err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs], |
195 | struct host1x_bo *cmdbuf, *target; | 229 | &relocs[num_relocs], drm, |
196 | 230 | file); | |
197 | cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf); | 231 | if (err < 0) |
198 | target = host1x_bo_lookup(drm, file, (u32)reloc->target); | ||
199 | |||
200 | reloc->cmdbuf = cmdbuf; | ||
201 | reloc->target = target; | ||
202 | |||
203 | if (!reloc->target || !reloc->cmdbuf) { | ||
204 | err = -ENOENT; | ||
205 | goto fail; | 232 | goto fail; |
206 | } | ||
207 | } | 233 | } |
208 | 234 | ||
209 | if (copy_from_user(job->waitchk, waitchks, | 235 | if (copy_from_user(job->waitchk, waitchks, |
@@ -455,11 +481,151 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data, | |||
455 | 481 | ||
456 | return 0; | 482 | return 0; |
457 | } | 483 | } |
484 | |||
485 | static int tegra_gem_set_tiling(struct drm_device *drm, void *data, | ||
486 | struct drm_file *file) | ||
487 | { | ||
488 | struct drm_tegra_gem_set_tiling *args = data; | ||
489 | enum tegra_bo_tiling_mode mode; | ||
490 | struct drm_gem_object *gem; | ||
491 | unsigned long value = 0; | ||
492 | struct tegra_bo *bo; | ||
493 | |||
494 | switch (args->mode) { | ||
495 | case DRM_TEGRA_GEM_TILING_MODE_PITCH: | ||
496 | mode = TEGRA_BO_TILING_MODE_PITCH; | ||
497 | |||
498 | if (args->value != 0) | ||
499 | return -EINVAL; | ||
500 | |||
501 | break; | ||
502 | |||
503 | case DRM_TEGRA_GEM_TILING_MODE_TILED: | ||
504 | mode = TEGRA_BO_TILING_MODE_TILED; | ||
505 | |||
506 | if (args->value != 0) | ||
507 | return -EINVAL; | ||
508 | |||
509 | break; | ||
510 | |||
511 | case DRM_TEGRA_GEM_TILING_MODE_BLOCK: | ||
512 | mode = TEGRA_BO_TILING_MODE_BLOCK; | ||
513 | |||
514 | if (args->value > 5) | ||
515 | return -EINVAL; | ||
516 | |||
517 | value = args->value; | ||
518 | break; | ||
519 | |||
520 | default: | ||
521 | return -EINVAL; | ||
522 | } | ||
523 | |||
524 | gem = drm_gem_object_lookup(drm, file, args->handle); | ||
525 | if (!gem) | ||
526 | return -ENOENT; | ||
527 | |||
528 | bo = to_tegra_bo(gem); | ||
529 | |||
530 | bo->tiling.mode = mode; | ||
531 | bo->tiling.value = value; | ||
532 | |||
533 | drm_gem_object_unreference(gem); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int tegra_gem_get_tiling(struct drm_device *drm, void *data, | ||
539 | struct drm_file *file) | ||
540 | { | ||
541 | struct drm_tegra_gem_get_tiling *args = data; | ||
542 | struct drm_gem_object *gem; | ||
543 | struct tegra_bo *bo; | ||
544 | int err = 0; | ||
545 | |||
546 | gem = drm_gem_object_lookup(drm, file, args->handle); | ||
547 | if (!gem) | ||
548 | return -ENOENT; | ||
549 | |||
550 | bo = to_tegra_bo(gem); | ||
551 | |||
552 | switch (bo->tiling.mode) { | ||
553 | case TEGRA_BO_TILING_MODE_PITCH: | ||
554 | args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH; | ||
555 | args->value = 0; | ||
556 | break; | ||
557 | |||
558 | case TEGRA_BO_TILING_MODE_TILED: | ||
559 | args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED; | ||
560 | args->value = 0; | ||
561 | break; | ||
562 | |||
563 | case TEGRA_BO_TILING_MODE_BLOCK: | ||
564 | args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK; | ||
565 | args->value = bo->tiling.value; | ||
566 | break; | ||
567 | |||
568 | default: | ||
569 | err = -EINVAL; | ||
570 | break; | ||
571 | } | ||
572 | |||
573 | drm_gem_object_unreference(gem); | ||
574 | |||
575 | return err; | ||
576 | } | ||
577 | |||
578 | static int tegra_gem_set_flags(struct drm_device *drm, void *data, | ||
579 | struct drm_file *file) | ||
580 | { | ||
581 | struct drm_tegra_gem_set_flags *args = data; | ||
582 | struct drm_gem_object *gem; | ||
583 | struct tegra_bo *bo; | ||
584 | |||
585 | if (args->flags & ~DRM_TEGRA_GEM_FLAGS) | ||
586 | return -EINVAL; | ||
587 | |||
588 | gem = drm_gem_object_lookup(drm, file, args->handle); | ||
589 | if (!gem) | ||
590 | return -ENOENT; | ||
591 | |||
592 | bo = to_tegra_bo(gem); | ||
593 | bo->flags = 0; | ||
594 | |||
595 | if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP) | ||
596 | bo->flags |= TEGRA_BO_BOTTOM_UP; | ||
597 | |||
598 | drm_gem_object_unreference(gem); | ||
599 | |||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static int tegra_gem_get_flags(struct drm_device *drm, void *data, | ||
604 | struct drm_file *file) | ||
605 | { | ||
606 | struct drm_tegra_gem_get_flags *args = data; | ||
607 | struct drm_gem_object *gem; | ||
608 | struct tegra_bo *bo; | ||
609 | |||
610 | gem = drm_gem_object_lookup(drm, file, args->handle); | ||
611 | if (!gem) | ||
612 | return -ENOENT; | ||
613 | |||
614 | bo = to_tegra_bo(gem); | ||
615 | args->flags = 0; | ||
616 | |||
617 | if (bo->flags & TEGRA_BO_BOTTOM_UP) | ||
618 | args->flags |= DRM_TEGRA_GEM_BOTTOM_UP; | ||
619 | |||
620 | drm_gem_object_unreference(gem); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
458 | #endif | 624 | #endif |
459 | 625 | ||
460 | static const struct drm_ioctl_desc tegra_drm_ioctls[] = { | 626 | static const struct drm_ioctl_desc tegra_drm_ioctls[] = { |
461 | #ifdef CONFIG_DRM_TEGRA_STAGING | 627 | #ifdef CONFIG_DRM_TEGRA_STAGING |
462 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH), | 628 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED), |
463 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED), | 629 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED), |
464 | DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED), | 630 | DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED), |
465 | DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED), | 631 | 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[] = { | |||
469 | DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED), | 635 | DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED), |
470 | DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), | 636 | DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), |
471 | DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED), | 637 | DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED), |
638 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED), | ||
639 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED), | ||
640 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED), | ||
641 | DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED), | ||
472 | #endif | 642 | #endif |
473 | }; | 643 | }; |
474 | 644 | ||
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 0d30689dff01..e89c70fa82d5 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <drm/drm_fb_helper.h> | 19 | #include <drm/drm_fb_helper.h> |
20 | #include <drm/drm_fixed.h> | 20 | #include <drm/drm_fixed.h> |
21 | 21 | ||
22 | #include "gem.h" | ||
23 | |||
22 | struct reset_control; | 24 | struct reset_control; |
23 | 25 | ||
24 | struct tegra_fb { | 26 | struct tegra_fb { |
@@ -43,6 +45,8 @@ struct tegra_drm { | |||
43 | #ifdef CONFIG_DRM_TEGRA_FBDEV | 45 | #ifdef CONFIG_DRM_TEGRA_FBDEV |
44 | struct tegra_fbdev *fbdev; | 46 | struct tegra_fbdev *fbdev; |
45 | #endif | 47 | #endif |
48 | |||
49 | unsigned int pitch_align; | ||
46 | }; | 50 | }; |
47 | 51 | ||
48 | struct tegra_drm_client; | 52 | struct tegra_drm_client; |
@@ -160,7 +164,8 @@ struct tegra_dc_window { | |||
160 | unsigned int stride[2]; | 164 | unsigned int stride[2]; |
161 | unsigned long base[3]; | 165 | unsigned long base[3]; |
162 | bool bottom_up; | 166 | bool bottom_up; |
163 | bool tiled; | 167 | |
168 | struct tegra_bo_tiling tiling; | ||
164 | }; | 169 | }; |
165 | 170 | ||
166 | /* from dc.c */ | 171 | /* from dc.c */ |
@@ -279,7 +284,8 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link, | |||
279 | struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, | 284 | struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, |
280 | unsigned int index); | 285 | unsigned int index); |
281 | bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer); | 286 | bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer); |
282 | bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); | 287 | int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, |
288 | struct tegra_bo_tiling *tiling); | ||
283 | int tegra_drm_fb_prepare(struct drm_device *drm); | 289 | int tegra_drm_fb_prepare(struct drm_device *drm); |
284 | int tegra_drm_fb_init(struct drm_device *drm); | 290 | int tegra_drm_fb_init(struct drm_device *drm); |
285 | void tegra_drm_fb_exit(struct drm_device *drm); | 291 | void tegra_drm_fb_exit(struct drm_device *drm); |
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index bd56f2affa78..f7874458926a 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c | |||
@@ -474,7 +474,8 @@ static int tegra_output_dsi_enable(struct tegra_output *output) | |||
474 | tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); | 474 | tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); |
475 | 475 | ||
476 | value = tegra_dsi_readl(dsi, DSI_CONTROL); | 476 | value = tegra_dsi_readl(dsi, DSI_CONTROL); |
477 | value |= DSI_CONTROL_HS_CLK_CTRL; | 477 | if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS) |
478 | value |= DSI_CONTROL_HS_CLK_CTRL; | ||
478 | value &= ~DSI_CONTROL_TX_TRIG(3); | 479 | value &= ~DSI_CONTROL_TX_TRIG(3); |
479 | value &= ~DSI_CONTROL_DCS_ENABLE; | 480 | value &= ~DSI_CONTROL_DCS_ENABLE; |
480 | value |= DSI_CONTROL_VIDEO_ENABLE; | 481 | value |= DSI_CONTROL_VIDEO_ENABLE; |
@@ -982,6 +983,7 @@ static const struct of_device_id tegra_dsi_of_match[] = { | |||
982 | { .compatible = "nvidia,tegra114-dsi", }, | 983 | { .compatible = "nvidia,tegra114-dsi", }, |
983 | { }, | 984 | { }, |
984 | }; | 985 | }; |
986 | MODULE_DEVICE_TABLE(of, tegra_dsi_of_match); | ||
985 | 987 | ||
986 | struct platform_driver tegra_dsi_driver = { | 988 | struct platform_driver tegra_dsi_driver = { |
987 | .driver = { | 989 | .driver = { |
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index fc1528e0bda1..3513d12d5aa1 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c | |||
@@ -46,14 +46,15 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer) | |||
46 | return false; | 46 | return false; |
47 | } | 47 | } |
48 | 48 | ||
49 | bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer) | 49 | int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer, |
50 | struct tegra_bo_tiling *tiling) | ||
50 | { | 51 | { |
51 | struct tegra_fb *fb = to_tegra_fb(framebuffer); | 52 | struct tegra_fb *fb = to_tegra_fb(framebuffer); |
52 | 53 | ||
53 | if (fb->planes[0]->flags & TEGRA_BO_TILED) | 54 | /* TODO: handle YUV formats? */ |
54 | return true; | 55 | *tiling = fb->planes[0]->tiling; |
55 | 56 | ||
56 | return false; | 57 | return 0; |
57 | } | 58 | } |
58 | 59 | ||
59 | static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) | 60 | static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) |
@@ -193,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, | |||
193 | struct drm_fb_helper_surface_size *sizes) | 194 | struct drm_fb_helper_surface_size *sizes) |
194 | { | 195 | { |
195 | struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); | 196 | struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); |
197 | struct tegra_drm *tegra = helper->dev->dev_private; | ||
196 | struct drm_device *drm = helper->dev; | 198 | struct drm_device *drm = helper->dev; |
197 | struct drm_mode_fb_cmd2 cmd = { 0 }; | 199 | struct drm_mode_fb_cmd2 cmd = { 0 }; |
198 | unsigned int bytes_per_pixel; | 200 | unsigned int bytes_per_pixel; |
@@ -207,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, | |||
207 | 209 | ||
208 | cmd.width = sizes->surface_width; | 210 | cmd.width = sizes->surface_width; |
209 | cmd.height = sizes->surface_height; | 211 | cmd.height = sizes->surface_height; |
210 | cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; | 212 | cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, |
213 | tegra->pitch_align); | ||
211 | cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, | 214 | cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, |
212 | sizes->surface_depth); | 215 | sizes->surface_depth); |
213 | 216 | ||
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index aa85b7b26f10..2545c7a468a2 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/dma-buf.h> | 16 | #include <linux/dma-buf.h> |
17 | #include <drm/tegra_drm.h> | 17 | #include <drm/tegra_drm.h> |
18 | 18 | ||
19 | #include "drm.h" | ||
19 | #include "gem.h" | 20 | #include "gem.h" |
20 | 21 | ||
21 | static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) | 22 | 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, | |||
126 | goto err_mmap; | 127 | goto err_mmap; |
127 | 128 | ||
128 | if (flags & DRM_TEGRA_GEM_CREATE_TILED) | 129 | if (flags & DRM_TEGRA_GEM_CREATE_TILED) |
129 | bo->flags |= TEGRA_BO_TILED; | 130 | bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED; |
130 | 131 | ||
131 | if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP) | 132 | if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP) |
132 | bo->flags |= TEGRA_BO_BOTTOM_UP; | 133 | bo->flags |= TEGRA_BO_BOTTOM_UP; |
@@ -259,8 +260,10 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, | |||
259 | struct drm_mode_create_dumb *args) | 260 | struct drm_mode_create_dumb *args) |
260 | { | 261 | { |
261 | int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); | 262 | int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); |
263 | struct tegra_drm *tegra = drm->dev_private; | ||
262 | struct tegra_bo *bo; | 264 | struct tegra_bo *bo; |
263 | 265 | ||
266 | min_pitch = round_up(min_pitch, tegra->pitch_align); | ||
264 | if (args->pitch < min_pitch) | 267 | if (args->pitch < min_pitch) |
265 | args->pitch = min_pitch; | 268 | args->pitch = min_pitch; |
266 | 269 | ||
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index 2f3fe96c5154..43a25c853357 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h | |||
@@ -16,8 +16,18 @@ | |||
16 | #include <drm/drm.h> | 16 | #include <drm/drm.h> |
17 | #include <drm/drmP.h> | 17 | #include <drm/drmP.h> |
18 | 18 | ||
19 | #define TEGRA_BO_TILED (1 << 0) | 19 | #define TEGRA_BO_BOTTOM_UP (1 << 0) |
20 | #define TEGRA_BO_BOTTOM_UP (1 << 1) | 20 | |
21 | enum tegra_bo_tiling_mode { | ||
22 | TEGRA_BO_TILING_MODE_PITCH, | ||
23 | TEGRA_BO_TILING_MODE_TILED, | ||
24 | TEGRA_BO_TILING_MODE_BLOCK, | ||
25 | }; | ||
26 | |||
27 | struct tegra_bo_tiling { | ||
28 | enum tegra_bo_tiling_mode mode; | ||
29 | unsigned long value; | ||
30 | }; | ||
21 | 31 | ||
22 | struct tegra_bo { | 32 | struct tegra_bo { |
23 | struct drm_gem_object gem; | 33 | struct drm_gem_object gem; |
@@ -26,6 +36,8 @@ struct tegra_bo { | |||
26 | struct sg_table *sgt; | 36 | struct sg_table *sgt; |
27 | dma_addr_t paddr; | 37 | dma_addr_t paddr; |
28 | void *vaddr; | 38 | void *vaddr; |
39 | |||
40 | struct tegra_bo_tiling tiling; | ||
29 | }; | 41 | }; |
30 | 42 | ||
31 | static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) | 43 | static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) |
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index 7c53941f2a9e..02cd3e37a6ec 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c | |||
@@ -121,6 +121,7 @@ static const struct of_device_id gr2d_match[] = { | |||
121 | { .compatible = "nvidia,tegra20-gr2d" }, | 121 | { .compatible = "nvidia,tegra20-gr2d" }, |
122 | { }, | 122 | { }, |
123 | }; | 123 | }; |
124 | MODULE_DEVICE_TABLE(of, gr2d_match); | ||
124 | 125 | ||
125 | static const u32 gr2d_addr_regs[] = { | 126 | static const u32 gr2d_addr_regs[] = { |
126 | GR2D_UA_BASE_ADDR, | 127 | GR2D_UA_BASE_ADDR, |
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index 30f5ba9bd6d0..2bea2b2d204e 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c | |||
@@ -130,6 +130,7 @@ static const struct of_device_id tegra_gr3d_match[] = { | |||
130 | { .compatible = "nvidia,tegra20-gr3d" }, | 130 | { .compatible = "nvidia,tegra20-gr3d" }, |
131 | { } | 131 | { } |
132 | }; | 132 | }; |
133 | MODULE_DEVICE_TABLE(of, tegra_gr3d_match); | ||
133 | 134 | ||
134 | static const u32 gr3d_addr_regs[] = { | 135 | static const u32 gr3d_addr_regs[] = { |
135 | GR3D_IDX_ATTRIBUTE( 0), | 136 | GR3D_IDX_ATTRIBUTE( 0), |
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index ba067bb767e3..ffe26547328d 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c | |||
@@ -1450,6 +1450,7 @@ static const struct of_device_id tegra_hdmi_of_match[] = { | |||
1450 | { .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config }, | 1450 | { .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config }, |
1451 | { }, | 1451 | { }, |
1452 | }; | 1452 | }; |
1453 | MODULE_DEVICE_TABLE(of, tegra_hdmi_of_match); | ||
1453 | 1454 | ||
1454 | static int tegra_hdmi_probe(struct platform_device *pdev) | 1455 | static int tegra_hdmi_probe(struct platform_device *pdev) |
1455 | { | 1456 | { |
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 27c979b50111..0410e467b828 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c | |||
@@ -516,7 +516,7 @@ static int tegra_output_sor_enable(struct tegra_output *output) | |||
516 | if (err < 0) { | 516 | if (err < 0) { |
517 | dev_err(sor->dev, "failed to probe eDP link: %d\n", | 517 | dev_err(sor->dev, "failed to probe eDP link: %d\n", |
518 | err); | 518 | err); |
519 | return err; | 519 | goto unlock; |
520 | } | 520 | } |
521 | } | 521 | } |
522 | 522 | ||
@@ -525,7 +525,7 @@ static int tegra_output_sor_enable(struct tegra_output *output) | |||
525 | dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); | 525 | dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); |
526 | 526 | ||
527 | memset(&config, 0, sizeof(config)); | 527 | memset(&config, 0, sizeof(config)); |
528 | config.bits_per_pixel = 24; /* XXX: don't hardcode? */ | 528 | config.bits_per_pixel = output->connector.display_info.bpc * 3; |
529 | 529 | ||
530 | err = tegra_sor_calc_config(sor, mode, &config, &link); | 530 | err = tegra_sor_calc_config(sor, mode, &config, &link); |
531 | if (err < 0) | 531 | if (err < 0) |
@@ -815,12 +815,22 @@ static int tegra_output_sor_enable(struct tegra_output *output) | |||
815 | * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete | 815 | * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete |
816 | * raster, associate with display controller) | 816 | * raster, associate with display controller) |
817 | */ | 817 | */ |
818 | value = SOR_STATE_ASY_VSYNCPOL | | 818 | value = SOR_STATE_ASY_PROTOCOL_DP_A | |
819 | SOR_STATE_ASY_HSYNCPOL | | ||
820 | SOR_STATE_ASY_PROTOCOL_DP_A | | ||
821 | SOR_STATE_ASY_CRC_MODE_COMPLETE | | 819 | SOR_STATE_ASY_CRC_MODE_COMPLETE | |
822 | SOR_STATE_ASY_OWNER(dc->pipe + 1); | 820 | SOR_STATE_ASY_OWNER(dc->pipe + 1); |
823 | 821 | ||
822 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) | ||
823 | value &= ~SOR_STATE_ASY_HSYNCPOL; | ||
824 | |||
825 | if (mode->flags & DRM_MODE_FLAG_NHSYNC) | ||
826 | value |= SOR_STATE_ASY_HSYNCPOL; | ||
827 | |||
828 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) | ||
829 | value &= ~SOR_STATE_ASY_VSYNCPOL; | ||
830 | |||
831 | if (mode->flags & DRM_MODE_FLAG_NVSYNC) | ||
832 | value |= SOR_STATE_ASY_VSYNCPOL; | ||
833 | |||
824 | switch (config.bits_per_pixel) { | 834 | switch (config.bits_per_pixel) { |
825 | case 24: | 835 | case 24: |
826 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; | 836 | value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; |
@@ -1455,6 +1465,7 @@ static const struct of_device_id tegra_sor_of_match[] = { | |||
1455 | { .compatible = "nvidia,tegra124-sor", }, | 1465 | { .compatible = "nvidia,tegra124-sor", }, |
1456 | { }, | 1466 | { }, |
1457 | }; | 1467 | }; |
1468 | MODULE_DEVICE_TABLE(of, tegra_sor_of_match); | ||
1458 | 1469 | ||
1459 | struct platform_driver tegra_sor_driver = { | 1470 | struct platform_driver tegra_sor_driver = { |
1460 | .driver = { | 1471 | .driver = { |
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index 112f27e51bc7..63bd63f3c7df 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c | |||
@@ -185,16 +185,16 @@ static unsigned int pin_job(struct host1x_job *job) | |||
185 | struct sg_table *sgt; | 185 | struct sg_table *sgt; |
186 | dma_addr_t phys_addr; | 186 | dma_addr_t phys_addr; |
187 | 187 | ||
188 | reloc->target = host1x_bo_get(reloc->target); | 188 | reloc->target.bo = host1x_bo_get(reloc->target.bo); |
189 | if (!reloc->target) | 189 | if (!reloc->target.bo) |
190 | goto unpin; | 190 | goto unpin; |
191 | 191 | ||
192 | phys_addr = host1x_bo_pin(reloc->target, &sgt); | 192 | phys_addr = host1x_bo_pin(reloc->target.bo, &sgt); |
193 | if (!phys_addr) | 193 | if (!phys_addr) |
194 | goto unpin; | 194 | goto unpin; |
195 | 195 | ||
196 | job->addr_phys[job->num_unpins] = phys_addr; | 196 | job->addr_phys[job->num_unpins] = phys_addr; |
197 | job->unpins[job->num_unpins].bo = reloc->target; | 197 | job->unpins[job->num_unpins].bo = reloc->target.bo; |
198 | job->unpins[job->num_unpins].sgt = sgt; | 198 | job->unpins[job->num_unpins].sgt = sgt; |
199 | job->num_unpins++; | 199 | job->num_unpins++; |
200 | } | 200 | } |
@@ -235,21 +235,21 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf) | |||
235 | for (i = 0; i < job->num_relocs; i++) { | 235 | for (i = 0; i < job->num_relocs; i++) { |
236 | struct host1x_reloc *reloc = &job->relocarray[i]; | 236 | struct host1x_reloc *reloc = &job->relocarray[i]; |
237 | u32 reloc_addr = (job->reloc_addr_phys[i] + | 237 | u32 reloc_addr = (job->reloc_addr_phys[i] + |
238 | reloc->target_offset) >> reloc->shift; | 238 | reloc->target.offset) >> reloc->shift; |
239 | u32 *target; | 239 | u32 *target; |
240 | 240 | ||
241 | /* skip all other gathers */ | 241 | /* skip all other gathers */ |
242 | if (cmdbuf != reloc->cmdbuf) | 242 | if (cmdbuf != reloc->cmdbuf.bo) |
243 | continue; | 243 | continue; |
244 | 244 | ||
245 | if (last_page != reloc->cmdbuf_offset >> PAGE_SHIFT) { | 245 | if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) { |
246 | if (cmdbuf_page_addr) | 246 | if (cmdbuf_page_addr) |
247 | host1x_bo_kunmap(cmdbuf, last_page, | 247 | host1x_bo_kunmap(cmdbuf, last_page, |
248 | cmdbuf_page_addr); | 248 | cmdbuf_page_addr); |
249 | 249 | ||
250 | cmdbuf_page_addr = host1x_bo_kmap(cmdbuf, | 250 | cmdbuf_page_addr = host1x_bo_kmap(cmdbuf, |
251 | reloc->cmdbuf_offset >> PAGE_SHIFT); | 251 | reloc->cmdbuf.offset >> PAGE_SHIFT); |
252 | last_page = reloc->cmdbuf_offset >> PAGE_SHIFT; | 252 | last_page = reloc->cmdbuf.offset >> PAGE_SHIFT; |
253 | 253 | ||
254 | if (unlikely(!cmdbuf_page_addr)) { | 254 | if (unlikely(!cmdbuf_page_addr)) { |
255 | pr_err("Could not map cmdbuf for relocation\n"); | 255 | 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) | |||
257 | } | 257 | } |
258 | } | 258 | } |
259 | 259 | ||
260 | target = cmdbuf_page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK); | 260 | target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK); |
261 | *target = reloc_addr; | 261 | *target = reloc_addr; |
262 | } | 262 | } |
263 | 263 | ||
@@ -272,7 +272,7 @@ static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf, | |||
272 | { | 272 | { |
273 | offset *= sizeof(u32); | 273 | offset *= sizeof(u32); |
274 | 274 | ||
275 | if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset) | 275 | if (reloc->cmdbuf.bo != cmdbuf || reloc->cmdbuf.offset != offset) |
276 | return false; | 276 | return false; |
277 | 277 | ||
278 | return true; | 278 | return true; |
diff --git a/include/linux/host1x.h b/include/linux/host1x.h index d2b52999e771..bb9840fd1e18 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h | |||
@@ -164,12 +164,15 @@ int host1x_job_submit(struct host1x_job *job); | |||
164 | */ | 164 | */ |
165 | 165 | ||
166 | struct host1x_reloc { | 166 | struct host1x_reloc { |
167 | struct host1x_bo *cmdbuf; | 167 | struct { |
168 | u32 cmdbuf_offset; | 168 | struct host1x_bo *bo; |
169 | struct host1x_bo *target; | 169 | unsigned long offset; |
170 | u32 target_offset; | 170 | } cmdbuf; |
171 | u32 shift; | 171 | struct { |
172 | u32 pad; | 172 | struct host1x_bo *bo; |
173 | unsigned long offset; | ||
174 | } target; | ||
175 | unsigned long shift; | ||
173 | }; | 176 | }; |
174 | 177 | ||
175 | struct host1x_job { | 178 | struct host1x_job { |
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index b75482112428..c15d781ecc0f 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h | |||
@@ -129,6 +129,44 @@ struct drm_tegra_submit { | |||
129 | __u32 reserved[5]; /* future expansion */ | 129 | __u32 reserved[5]; /* future expansion */ |
130 | }; | 130 | }; |
131 | 131 | ||
132 | #define DRM_TEGRA_GEM_TILING_MODE_PITCH 0 | ||
133 | #define DRM_TEGRA_GEM_TILING_MODE_TILED 1 | ||
134 | #define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2 | ||
135 | |||
136 | struct drm_tegra_gem_set_tiling { | ||
137 | /* input */ | ||
138 | __u32 handle; | ||
139 | __u32 mode; | ||
140 | __u32 value; | ||
141 | __u32 pad; | ||
142 | }; | ||
143 | |||
144 | struct drm_tegra_gem_get_tiling { | ||
145 | /* input */ | ||
146 | __u32 handle; | ||
147 | /* output */ | ||
148 | __u32 mode; | ||
149 | __u32 value; | ||
150 | __u32 pad; | ||
151 | }; | ||
152 | |||
153 | #define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0) | ||
154 | #define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP) | ||
155 | |||
156 | struct drm_tegra_gem_set_flags { | ||
157 | /* input */ | ||
158 | __u32 handle; | ||
159 | /* output */ | ||
160 | __u32 flags; | ||
161 | }; | ||
162 | |||
163 | struct drm_tegra_gem_get_flags { | ||
164 | /* input */ | ||
165 | __u32 handle; | ||
166 | /* output */ | ||
167 | __u32 flags; | ||
168 | }; | ||
169 | |||
132 | #define DRM_TEGRA_GEM_CREATE 0x00 | 170 | #define DRM_TEGRA_GEM_CREATE 0x00 |
133 | #define DRM_TEGRA_GEM_MMAP 0x01 | 171 | #define DRM_TEGRA_GEM_MMAP 0x01 |
134 | #define DRM_TEGRA_SYNCPT_READ 0x02 | 172 | #define DRM_TEGRA_SYNCPT_READ 0x02 |
@@ -139,6 +177,10 @@ struct drm_tegra_submit { | |||
139 | #define DRM_TEGRA_GET_SYNCPT 0x07 | 177 | #define DRM_TEGRA_GET_SYNCPT 0x07 |
140 | #define DRM_TEGRA_SUBMIT 0x08 | 178 | #define DRM_TEGRA_SUBMIT 0x08 |
141 | #define DRM_TEGRA_GET_SYNCPT_BASE 0x09 | 179 | #define DRM_TEGRA_GET_SYNCPT_BASE 0x09 |
180 | #define DRM_TEGRA_GEM_SET_TILING 0x0a | ||
181 | #define DRM_TEGRA_GEM_GET_TILING 0x0b | ||
182 | #define DRM_TEGRA_GEM_SET_FLAGS 0x0c | ||
183 | #define DRM_TEGRA_GEM_GET_FLAGS 0x0d | ||
142 | 184 | ||
143 | #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) | 185 | #define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) |
144 | #define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) | 186 | #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 { | |||
150 | #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) | 192 | #define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) |
151 | #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) | 193 | #define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) |
152 | #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) | 194 | #define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) |
195 | #define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling) | ||
196 | #define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling) | ||
197 | #define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags) | ||
198 | #define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags) | ||
153 | 199 | ||
154 | #endif | 200 | #endif |