diff options
Diffstat (limited to 'drivers/gpu/drm/tegra')
-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 | 216 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dsi.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/fb.c | 66 | ||||
-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/output.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/sor.c | 21 |
14 files changed, 404 insertions, 73 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 3396f9f6a9f7..59736bb810cd 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c | |||
@@ -40,6 +40,12 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
40 | 40 | ||
41 | drm_mode_config_init(drm); | 41 | drm_mode_config_init(drm); |
42 | 42 | ||
43 | err = tegra_drm_fb_prepare(drm); | ||
44 | if (err < 0) | ||
45 | return err; | ||
46 | |||
47 | drm_kms_helper_poll_init(drm); | ||
48 | |||
43 | err = host1x_device_init(device); | 49 | err = host1x_device_init(device); |
44 | if (err < 0) | 50 | if (err < 0) |
45 | return err; | 51 | return err; |
@@ -59,8 +65,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags) | |||
59 | if (err < 0) | 65 | if (err < 0) |
60 | return err; | 66 | return err; |
61 | 67 | ||
62 | drm_kms_helper_poll_init(drm); | ||
63 | |||
64 | return 0; | 68 | return 0; |
65 | } | 69 | } |
66 | 70 | ||
@@ -128,6 +132,45 @@ host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle) | |||
128 | return &bo->base; | 132 | return &bo->base; |
129 | } | 133 | } |
130 | 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 | |||
131 | int tegra_drm_submit(struct tegra_drm_context *context, | 174 | int tegra_drm_submit(struct tegra_drm_context *context, |
132 | struct drm_tegra_submit *args, struct drm_device *drm, | 175 | struct drm_tegra_submit *args, struct drm_device *drm, |
133 | struct drm_file *file) | 176 | struct drm_file *file) |
@@ -180,26 +223,13 @@ int tegra_drm_submit(struct tegra_drm_context *context, | |||
180 | cmdbufs++; | 223 | cmdbufs++; |
181 | } | 224 | } |
182 | 225 | ||
183 | if (copy_from_user(job->relocarray, relocs, | 226 | /* copy and resolve relocations from submit */ |
184 | sizeof(*relocs) * num_relocs)) { | ||
185 | err = -EFAULT; | ||
186 | goto fail; | ||
187 | } | ||
188 | |||
189 | while (num_relocs--) { | 227 | while (num_relocs--) { |
190 | struct host1x_reloc *reloc = &job->relocarray[num_relocs]; | 228 | err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs], |
191 | struct host1x_bo *cmdbuf, *target; | 229 | &relocs[num_relocs], drm, |
192 | 230 | file); | |
193 | cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf); | 231 | if (err < 0) |
194 | target = host1x_bo_lookup(drm, file, (u32)reloc->target); | ||
195 | |||
196 | reloc->cmdbuf = cmdbuf; | ||
197 | reloc->target = target; | ||
198 | |||
199 | if (!reloc->target || !reloc->cmdbuf) { | ||
200 | err = -ENOENT; | ||
201 | goto fail; | 232 | goto fail; |
202 | } | ||
203 | } | 233 | } |
204 | 234 | ||
205 | if (copy_from_user(job->waitchk, waitchks, | 235 | if (copy_from_user(job->waitchk, waitchks, |
@@ -451,11 +481,151 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data, | |||
451 | 481 | ||
452 | return 0; | 482 | return 0; |
453 | } | 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 | } | ||
454 | #endif | 624 | #endif |
455 | 625 | ||
456 | static const struct drm_ioctl_desc tegra_drm_ioctls[] = { | 626 | static const struct drm_ioctl_desc tegra_drm_ioctls[] = { |
457 | #ifdef CONFIG_DRM_TEGRA_STAGING | 627 | #ifdef CONFIG_DRM_TEGRA_STAGING |
458 | 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), |
459 | 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), |
460 | 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), |
461 | 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), |
@@ -465,6 +635,10 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = { | |||
465 | 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), |
466 | DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), | 636 | DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), |
467 | 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), | ||
468 | #endif | 642 | #endif |
469 | }; | 643 | }; |
470 | 644 | ||
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 6b8fe9d86ed4..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,9 @@ 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); | ||
289 | int tegra_drm_fb_prepare(struct drm_device *drm); | ||
283 | int tegra_drm_fb_init(struct drm_device *drm); | 290 | int tegra_drm_fb_init(struct drm_device *drm); |
284 | void tegra_drm_fb_exit(struct drm_device *drm); | 291 | void tegra_drm_fb_exit(struct drm_device *drm); |
285 | #ifdef CONFIG_DRM_TEGRA_FBDEV | 292 | #ifdef CONFIG_DRM_TEGRA_FBDEV |
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 9798a7080322..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 | ||
@@ -267,18 +270,13 @@ release: | |||
267 | return err; | 270 | return err; |
268 | } | 271 | } |
269 | 272 | ||
270 | static struct drm_fb_helper_funcs tegra_fb_helper_funcs = { | 273 | static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = { |
271 | .fb_probe = tegra_fbdev_probe, | 274 | .fb_probe = tegra_fbdev_probe, |
272 | }; | 275 | }; |
273 | 276 | ||
274 | static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm, | 277 | static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm) |
275 | unsigned int preferred_bpp, | ||
276 | unsigned int num_crtc, | ||
277 | unsigned int max_connectors) | ||
278 | { | 278 | { |
279 | struct drm_fb_helper *helper; | ||
280 | struct tegra_fbdev *fbdev; | 279 | struct tegra_fbdev *fbdev; |
281 | int err; | ||
282 | 280 | ||
283 | fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); | 281 | fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); |
284 | if (!fbdev) { | 282 | if (!fbdev) { |
@@ -286,13 +284,23 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm, | |||
286 | return ERR_PTR(-ENOMEM); | 284 | return ERR_PTR(-ENOMEM); |
287 | } | 285 | } |
288 | 286 | ||
289 | fbdev->base.funcs = &tegra_fb_helper_funcs; | 287 | drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs); |
290 | helper = &fbdev->base; | 288 | |
289 | return fbdev; | ||
290 | } | ||
291 | |||
292 | static int tegra_fbdev_init(struct tegra_fbdev *fbdev, | ||
293 | unsigned int preferred_bpp, | ||
294 | unsigned int num_crtc, | ||
295 | unsigned int max_connectors) | ||
296 | { | ||
297 | struct drm_device *drm = fbdev->base.dev; | ||
298 | int err; | ||
291 | 299 | ||
292 | err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors); | 300 | err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors); |
293 | if (err < 0) { | 301 | if (err < 0) { |
294 | dev_err(drm->dev, "failed to initialize DRM FB helper\n"); | 302 | dev_err(drm->dev, "failed to initialize DRM FB helper\n"); |
295 | goto free; | 303 | return err; |
296 | } | 304 | } |
297 | 305 | ||
298 | err = drm_fb_helper_single_add_all_connectors(&fbdev->base); | 306 | err = drm_fb_helper_single_add_all_connectors(&fbdev->base); |
@@ -301,21 +309,17 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm, | |||
301 | goto fini; | 309 | goto fini; |
302 | } | 310 | } |
303 | 311 | ||
304 | drm_helper_disable_unused_functions(drm); | ||
305 | |||
306 | err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp); | 312 | err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp); |
307 | if (err < 0) { | 313 | if (err < 0) { |
308 | dev_err(drm->dev, "failed to set initial configuration\n"); | 314 | dev_err(drm->dev, "failed to set initial configuration\n"); |
309 | goto fini; | 315 | goto fini; |
310 | } | 316 | } |
311 | 317 | ||
312 | return fbdev; | 318 | return 0; |
313 | 319 | ||
314 | fini: | 320 | fini: |
315 | drm_fb_helper_fini(&fbdev->base); | 321 | drm_fb_helper_fini(&fbdev->base); |
316 | free: | 322 | return err; |
317 | kfree(fbdev); | ||
318 | return ERR_PTR(err); | ||
319 | } | 323 | } |
320 | 324 | ||
321 | static void tegra_fbdev_free(struct tegra_fbdev *fbdev) | 325 | static void tegra_fbdev_free(struct tegra_fbdev *fbdev) |
@@ -366,7 +370,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_funcs = { | |||
366 | #endif | 370 | #endif |
367 | }; | 371 | }; |
368 | 372 | ||
369 | int tegra_drm_fb_init(struct drm_device *drm) | 373 | int tegra_drm_fb_prepare(struct drm_device *drm) |
370 | { | 374 | { |
371 | #ifdef CONFIG_DRM_TEGRA_FBDEV | 375 | #ifdef CONFIG_DRM_TEGRA_FBDEV |
372 | struct tegra_drm *tegra = drm->dev_private; | 376 | struct tegra_drm *tegra = drm->dev_private; |
@@ -381,8 +385,7 @@ int tegra_drm_fb_init(struct drm_device *drm) | |||
381 | drm->mode_config.funcs = &tegra_drm_mode_funcs; | 385 | drm->mode_config.funcs = &tegra_drm_mode_funcs; |
382 | 386 | ||
383 | #ifdef CONFIG_DRM_TEGRA_FBDEV | 387 | #ifdef CONFIG_DRM_TEGRA_FBDEV |
384 | tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc, | 388 | tegra->fbdev = tegra_fbdev_create(drm); |
385 | drm->mode_config.num_connector); | ||
386 | if (IS_ERR(tegra->fbdev)) | 389 | if (IS_ERR(tegra->fbdev)) |
387 | return PTR_ERR(tegra->fbdev); | 390 | return PTR_ERR(tegra->fbdev); |
388 | #endif | 391 | #endif |
@@ -390,6 +393,21 @@ int tegra_drm_fb_init(struct drm_device *drm) | |||
390 | return 0; | 393 | return 0; |
391 | } | 394 | } |
392 | 395 | ||
396 | int tegra_drm_fb_init(struct drm_device *drm) | ||
397 | { | ||
398 | #ifdef CONFIG_DRM_TEGRA_FBDEV | ||
399 | struct tegra_drm *tegra = drm->dev_private; | ||
400 | int err; | ||
401 | |||
402 | err = tegra_fbdev_init(tegra->fbdev, 32, drm->mode_config.num_crtc, | ||
403 | drm->mode_config.num_connector); | ||
404 | if (err < 0) | ||
405 | return err; | ||
406 | #endif | ||
407 | |||
408 | return 0; | ||
409 | } | ||
410 | |||
393 | void tegra_drm_fb_exit(struct drm_device *drm) | 411 | void tegra_drm_fb_exit(struct drm_device *drm) |
394 | { | 412 | { |
395 | #ifdef CONFIG_DRM_TEGRA_FBDEV | 413 | #ifdef CONFIG_DRM_TEGRA_FBDEV |
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 78cc8143760a..ce023fa3e8ae 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/output.c b/drivers/gpu/drm/tegra/output.c index a3e4f1eca6f7..0c67d7eebc94 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c | |||
@@ -105,7 +105,7 @@ static void drm_connector_clear(struct drm_connector *connector) | |||
105 | 105 | ||
106 | static void tegra_connector_destroy(struct drm_connector *connector) | 106 | static void tegra_connector_destroy(struct drm_connector *connector) |
107 | { | 107 | { |
108 | drm_sysfs_connector_remove(connector); | 108 | drm_connector_unregister(connector); |
109 | drm_connector_cleanup(connector); | 109 | drm_connector_cleanup(connector); |
110 | drm_connector_clear(connector); | 110 | drm_connector_clear(connector); |
111 | } | 111 | } |
@@ -140,7 +140,9 @@ static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode) | |||
140 | if (mode != DRM_MODE_DPMS_ON) { | 140 | if (mode != DRM_MODE_DPMS_ON) { |
141 | drm_panel_disable(panel); | 141 | drm_panel_disable(panel); |
142 | tegra_output_disable(output); | 142 | tegra_output_disable(output); |
143 | drm_panel_unprepare(panel); | ||
143 | } else { | 144 | } else { |
145 | drm_panel_prepare(panel); | ||
144 | tegra_output_enable(output); | 146 | tegra_output_enable(output); |
145 | drm_panel_enable(panel); | 147 | drm_panel_enable(panel); |
146 | } | 148 | } |
@@ -318,7 +320,7 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output) | |||
318 | drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); | 320 | drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); |
319 | 321 | ||
320 | drm_mode_connector_attach_encoder(&output->connector, &output->encoder); | 322 | drm_mode_connector_attach_encoder(&output->connector, &output->encoder); |
321 | drm_sysfs_connector_add(&output->connector); | 323 | drm_connector_register(&output->connector); |
322 | 324 | ||
323 | output->encoder.possible_crtcs = 0x3; | 325 | output->encoder.possible_crtcs = 0x3; |
324 | 326 | ||
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 = { |