summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r--drivers/gpu/drm/tegra/Kconfig1
-rw-r--r--drivers/gpu/drm/tegra/dc.c50
-rw-r--r--drivers/gpu/drm/tegra/dc.h7
-rw-r--r--drivers/gpu/drm/tegra/dp.c13
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c7
-rw-r--r--drivers/gpu/drm/tegra/drm.c3
-rw-r--r--drivers/gpu/drm/tegra/dsi.c4
-rw-r--r--drivers/gpu/drm/tegra/gem.c10
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c34
-rw-r--r--drivers/gpu/drm/tegra/hub.c24
-rw-r--r--drivers/gpu/drm/tegra/plane.c73
-rw-r--r--drivers/gpu/drm/tegra/plane.h2
-rw-r--r--drivers/gpu/drm/tegra/sor.c2
13 files changed, 157 insertions, 73 deletions
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig
index 201f5175ecfe..6ed55ebaec8c 100644
--- a/drivers/gpu/drm/tegra/Kconfig
+++ b/drivers/gpu/drm/tegra/Kconfig
@@ -6,6 +6,7 @@ config DRM_TEGRA
depends on DRM
depends on OF
select DRM_DP_AUX_BUS
+ select DRM_DP_HELPER
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index eb70eee8992a..c6951cf5d2ca 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -345,18 +345,19 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
{
unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
struct tegra_dc *dc = plane->dc;
- bool yuv, planar;
+ unsigned int planes;
u32 value;
+ bool yuv;
/*
* For YUV planar modes, the number of bytes per pixel takes into
* account only the luma component and therefore is 1.
*/
- yuv = tegra_plane_format_is_yuv(window->format, &planar, NULL);
+ yuv = tegra_plane_format_is_yuv(window->format, &planes, NULL);
if (!yuv)
bpp = window->bits_per_pixel / 8;
else
- bpp = planar ? 1 : 2;
+ bpp = (planes > 1) ? 1 : 2;
tegra_plane_writel(plane, window->format, DC_WIN_COLOR_DEPTH);
tegra_plane_writel(plane, window->swap, DC_WIN_BYTE_SWAP);
@@ -385,7 +386,7 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
* For DDA computations the number of bytes per pixel for YUV planar
* modes needs to take into account all Y, U and V components.
*/
- if (yuv && planar)
+ if (yuv && planes > 1)
bpp = 2;
h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp);
@@ -405,9 +406,12 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
tegra_plane_writel(plane, window->base[0], DC_WINBUF_START_ADDR);
- if (yuv && planar) {
+ if (yuv && planes > 1) {
tegra_plane_writel(plane, window->base[1], DC_WINBUF_START_ADDR_U);
- tegra_plane_writel(plane, window->base[2], DC_WINBUF_START_ADDR_V);
+
+ if (planes > 2)
+ tegra_plane_writel(plane, window->base[2], DC_WINBUF_START_ADDR_V);
+
value = window->stride[1] << 16 | window->stride[0];
tegra_plane_writel(plane, value, DC_WIN_LINE_STRIDE);
} else {
@@ -1193,6 +1197,13 @@ static const u32 tegra114_overlay_formats[] = {
DRM_FORMAT_YUYV,
DRM_FORMAT_YUV420,
DRM_FORMAT_YUV422,
+ /* semi-planar formats */
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_NV16,
+ DRM_FORMAT_NV61,
+ DRM_FORMAT_NV24,
+ DRM_FORMAT_NV42,
};
static const u32 tegra124_overlay_formats[] = {
@@ -1221,8 +1232,18 @@ static const u32 tegra124_overlay_formats[] = {
/* planar formats */
DRM_FORMAT_UYVY,
DRM_FORMAT_YUYV,
- DRM_FORMAT_YUV420,
- DRM_FORMAT_YUV422,
+ DRM_FORMAT_YVYU,
+ DRM_FORMAT_VYUY,
+ DRM_FORMAT_YUV420, /* YU12 */
+ DRM_FORMAT_YUV422, /* YU16 */
+ DRM_FORMAT_YUV444, /* YU24 */
+ /* semi-planar formats */
+ DRM_FORMAT_NV12,
+ DRM_FORMAT_NV21,
+ DRM_FORMAT_NV16,
+ DRM_FORMAT_NV61,
+ DRM_FORMAT_NV24,
+ DRM_FORMAT_NV42,
};
static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
@@ -3211,16 +3232,9 @@ static int tegra_dc_probe(struct platform_device *pdev)
return -ENXIO;
err = tegra_dc_rgb_probe(dc);
- if (err < 0 && err != -ENODEV) {
- const char *level = KERN_ERR;
-
- if (err == -EPROBE_DEFER)
- level = KERN_DEBUG;
-
- dev_printk(level, dc->dev, "failed to probe RGB output: %d\n",
- err);
- return err;
- }
+ if (err < 0 && err != -ENODEV)
+ return dev_err_probe(&pdev->dev, err,
+ "failed to probe RGB output\n");
platform_set_drvdata(pdev, dc);
pm_runtime_enable(&pdev->dev);
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 3f91a10ea6c7..f902794d42cc 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -637,6 +637,13 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define WIN_COLOR_DEPTH_A8B8G8R8 36
#define WIN_COLOR_DEPTH_B8G8R8X8 37
#define WIN_COLOR_DEPTH_R8G8B8X8 38
+#define WIN_COLOR_DEPTH_YCbCr444P 41
+#define WIN_COLOR_DEPTH_YCrCb420SP 42
+#define WIN_COLOR_DEPTH_YCbCr420SP 43
+#define WIN_COLOR_DEPTH_YCrCb422SP 44
+#define WIN_COLOR_DEPTH_YCbCr422SP 45
+#define WIN_COLOR_DEPTH_YCrCb444SP 48
+#define WIN_COLOR_DEPTH_YCbCr444SP 49
#define WIN_COLOR_DEPTH_X8B8G8R8 65
#define WIN_COLOR_DEPTH_X8R8G8B8 66
diff --git a/drivers/gpu/drm/tegra/dp.c b/drivers/gpu/drm/tegra/dp.c
index 70dfb7d1dec5..7295975e5733 100644
--- a/drivers/gpu/drm/tegra/dp.c
+++ b/drivers/gpu/drm/tegra/dp.c
@@ -5,7 +5,7 @@
*/
#include <drm/drm_crtc.h>
-#include <drm/drm_dp_helper.h>
+#include <drm/dp/drm_dp_helper.h>
#include <drm/drm_print.h>
#include "dp.h"
@@ -549,6 +549,15 @@ static void drm_dp_link_get_adjustments(struct drm_dp_link *link,
{
struct drm_dp_link_train_set *adjust = &link->train.adjust;
unsigned int i;
+ u8 post_cursor;
+ int err;
+
+ err = drm_dp_dpcd_read(link->aux, DP_ADJUST_REQUEST_POST_CURSOR2,
+ &post_cursor, sizeof(post_cursor));
+ if (err < 0) {
+ DRM_ERROR("failed to read post_cursor2: %d\n", err);
+ post_cursor = 0;
+ }
for (i = 0; i < link->lanes; i++) {
adjust->voltage_swing[i] =
@@ -560,7 +569,7 @@ static void drm_dp_link_get_adjustments(struct drm_dp_link *link,
DP_TRAIN_PRE_EMPHASIS_SHIFT;
adjust->post_cursor[i] =
- drm_dp_get_adjust_request_post_cursor(status, i);
+ (post_cursor >> (i << 1)) & 0x3;
}
}
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index d7a731d287d2..20e1dd6b3bf0 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -18,8 +18,8 @@
#include <linux/reset.h>
#include <linux/workqueue.h>
-#include <drm/drm_dp_helper.h>
-#include <drm/drm_dp_aux_bus.h>
+#include <drm/dp/drm_dp_helper.h>
+#include <drm/dp/drm_dp_aux_bus.h>
#include <drm/drm_panel.h>
#include "dp.h"
@@ -280,7 +280,6 @@ static void tegra_dpaux_hotplug(struct work_struct *work)
static irqreturn_t tegra_dpaux_irq(int irq, void *data)
{
struct tegra_dpaux *dpaux = data;
- irqreturn_t ret = IRQ_HANDLED;
u32 value;
/* clear interrupts */
@@ -297,7 +296,7 @@ static irqreturn_t tegra_dpaux_irq(int irq, void *data)
if (value & DPAUX_INTR_AUX_DONE)
complete(&dpaux->complete);
- return ret;
+ return IRQ_HANDLED;
}
enum tegra_dpaux_functions {
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index e9de91a4e7e8..9464f522e257 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1410,6 +1410,9 @@ static int __init host1x_drm_init(void)
{
int err;
+ if (drm_firmware_drivers_only())
+ return -ENODEV;
+
err = host1x_driver_register(&host1x_drm_driver);
if (err < 0)
return err;
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index f46d377f0c30..de1333dc0d86 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -1538,8 +1538,10 @@ static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
dsi->slave = platform_get_drvdata(gangster);
of_node_put(np);
- if (!dsi->slave)
+ if (!dsi->slave) {
+ put_device(&gangster->dev);
return -EPROBE_DEFER;
+ }
dsi->slave->master = dsi;
}
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index fce0e52973c2..0063403ab5e1 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -174,7 +174,7 @@ static void tegra_bo_unpin(struct host1x_bo_mapping *map)
static void *tegra_bo_mmap(struct host1x_bo *bo)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
- struct dma_buf_map map;
+ struct iosys_map map;
int ret;
if (obj->vaddr) {
@@ -191,7 +191,7 @@ static void *tegra_bo_mmap(struct host1x_bo *bo)
static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
{
struct tegra_bo *obj = host1x_to_tegra_bo(bo);
- struct dma_buf_map map = DMA_BUF_MAP_INIT_VADDR(addr);
+ struct iosys_map map = IOSYS_MAP_INIT_VADDR(addr);
if (obj->vaddr)
return;
@@ -699,17 +699,17 @@ static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
return __tegra_gem_mmap(gem, vma);
}
-static int tegra_gem_prime_vmap(struct dma_buf *buf, struct dma_buf_map *map)
+static int tegra_gem_prime_vmap(struct dma_buf *buf, struct iosys_map *map)
{
struct drm_gem_object *gem = buf->priv;
struct tegra_bo *bo = to_tegra_bo(gem);
- dma_buf_map_set_vaddr(map, bo->vaddr);
+ iosys_map_set_vaddr(map, bo->vaddr);
return 0;
}
-static void tegra_gem_prime_vunmap(struct dma_buf *buf, struct dma_buf_map *map)
+static void tegra_gem_prime_vunmap(struct dma_buf *buf, struct iosys_map *map)
{
}
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 8845af5d325f..bf240767dad9 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1775,7 +1775,6 @@ static irqreturn_t tegra_hdmi_irq(int irq, void *data)
static int tegra_hdmi_probe(struct platform_device *pdev)
{
- const char *level = KERN_ERR;
struct tegra_hdmi *hdmi;
struct resource *regs;
int err;
@@ -1817,36 +1816,21 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
hdmi->hdmi = devm_regulator_get(&pdev->dev, "hdmi");
err = PTR_ERR_OR_ZERO(hdmi->hdmi);
- if (err) {
- if (err == -EPROBE_DEFER)
- level = KERN_DEBUG;
-
- dev_printk(level, &pdev->dev,
- "failed to get HDMI regulator: %d\n", err);
- return err;
- }
+ if (err)
+ return dev_err_probe(&pdev->dev, err,
+ "failed to get HDMI regulator\n");
hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
err = PTR_ERR_OR_ZERO(hdmi->pll);
- if (err) {
- if (err == -EPROBE_DEFER)
- level = KERN_DEBUG;
-
- dev_printk(level, &pdev->dev,
- "failed to get PLL regulator: %d\n", err);
- return err;
- }
+ if (err)
+ return dev_err_probe(&pdev->dev, err,
+ "failed to get PLL regulator\n");
hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
err = PTR_ERR_OR_ZERO(hdmi->vdd);
- if (err) {
- if (err == -EPROBE_DEFER)
- level = KERN_DEBUG;
-
- dev_printk(level, &pdev->dev,
- "failed to get VDD regulator: %d\n", err);
- return err;
- }
+ if (err)
+ return dev_err_probe(&pdev->dev, err,
+ "failed to get VDD regulator\n");
hdmi->output.dev = &pdev->dev;
diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c
index b910155f80c4..b8d3174c04c9 100644
--- a/drivers/gpu/drm/tegra/hub.c
+++ b/drivers/gpu/drm/tegra/hub.c
@@ -540,8 +540,8 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
struct tegra_plane *p = to_tegra_plane(plane);
u32 value, min_width, bypass = 0;
dma_addr_t base, addr_flag = 0;
- unsigned int bpc;
- bool yuv, planar;
+ unsigned int bpc, planes;
+ bool yuv;
int err;
/* rien ne va plus */
@@ -559,7 +559,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
return;
}
- yuv = tegra_plane_format_is_yuv(tegra_plane_state->format, &planar, &bpc);
+ yuv = tegra_plane_format_is_yuv(tegra_plane_state->format, &planes, &bpc);
tegra_dc_assign_shared_plane(dc, p);
@@ -660,20 +660,26 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
value = PITCH(fb->pitches[0]);
tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE);
- if (yuv && planar) {
+ if (yuv && planes > 1) {
base = tegra_plane_state->iova[1] + fb->offsets[1];
base |= addr_flag;
tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_U);
tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_U);
- base = tegra_plane_state->iova[2] + fb->offsets[2];
- base |= addr_flag;
+ if (planes > 2) {
+ base = tegra_plane_state->iova[2] + fb->offsets[2];
+ base |= addr_flag;
+
+ tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_V);
+ tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_V);
+ }
+
+ value = PITCH_U(fb->pitches[1]);
- tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_V);
- tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_V);
+ if (planes > 2)
+ value |= PITCH_V(fb->pitches[2]);
- value = PITCH_U(fb->pitches[2]) | PITCH_V(fb->pitches[2]);
tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE_UV);
} else {
tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_U);
diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c
index 321cb1f13da6..e0e6938c6200 100644
--- a/drivers/gpu/drm/tegra/plane.c
+++ b/drivers/gpu/drm/tegra/plane.c
@@ -413,6 +413,22 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
*swap = BYTE_SWAP_SWAP2;
break;
+ case DRM_FORMAT_YVYU:
+ if (!swap)
+ return -EINVAL;
+
+ *format = WIN_COLOR_DEPTH_YCbCr422;
+ *swap = BYTE_SWAP_SWAP4;
+ break;
+
+ case DRM_FORMAT_VYUY:
+ if (!swap)
+ return -EINVAL;
+
+ *format = WIN_COLOR_DEPTH_YCbCr422;
+ *swap = BYTE_SWAP_SWAP4HW;
+ break;
+
case DRM_FORMAT_YUV420:
*format = WIN_COLOR_DEPTH_YCbCr420P;
break;
@@ -421,6 +437,34 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
*format = WIN_COLOR_DEPTH_YCbCr422P;
break;
+ case DRM_FORMAT_YUV444:
+ *format = WIN_COLOR_DEPTH_YCbCr444P;
+ break;
+
+ case DRM_FORMAT_NV12:
+ *format = WIN_COLOR_DEPTH_YCbCr420SP;
+ break;
+
+ case DRM_FORMAT_NV21:
+ *format = WIN_COLOR_DEPTH_YCrCb420SP;
+ break;
+
+ case DRM_FORMAT_NV16:
+ *format = WIN_COLOR_DEPTH_YCbCr422SP;
+ break;
+
+ case DRM_FORMAT_NV61:
+ *format = WIN_COLOR_DEPTH_YCrCb422SP;
+ break;
+
+ case DRM_FORMAT_NV24:
+ *format = WIN_COLOR_DEPTH_YCbCr444SP;
+ break;
+
+ case DRM_FORMAT_NV42:
+ *format = WIN_COLOR_DEPTH_YCrCb444SP;
+ break;
+
default:
return -EINVAL;
}
@@ -441,13 +485,13 @@ bool tegra_plane_format_is_indexed(unsigned int format)
return false;
}
-bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *bpc)
+bool tegra_plane_format_is_yuv(unsigned int format, unsigned int *planes, unsigned int *bpc)
{
switch (format) {
case WIN_COLOR_DEPTH_YCbCr422:
case WIN_COLOR_DEPTH_YUV422:
- if (planar)
- *planar = false;
+ if (planes)
+ *planes = 1;
if (bpc)
*bpc = 8;
@@ -462,8 +506,23 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *
case WIN_COLOR_DEPTH_YUV422R:
case WIN_COLOR_DEPTH_YCbCr422RA:
case WIN_COLOR_DEPTH_YUV422RA:
- if (planar)
- *planar = true;
+ case WIN_COLOR_DEPTH_YCbCr444P:
+ if (planes)
+ *planes = 3;
+
+ if (bpc)
+ *bpc = 8;
+
+ return true;
+
+ case WIN_COLOR_DEPTH_YCrCb420SP:
+ case WIN_COLOR_DEPTH_YCbCr420SP:
+ case WIN_COLOR_DEPTH_YCrCb422SP:
+ case WIN_COLOR_DEPTH_YCbCr422SP:
+ case WIN_COLOR_DEPTH_YCrCb444SP:
+ case WIN_COLOR_DEPTH_YCbCr444SP:
+ if (planes)
+ *planes = 2;
if (bpc)
*bpc = 8;
@@ -471,8 +530,8 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *
return true;
}
- if (planar)
- *planar = false;
+ if (planes)
+ *planes = 1;
return false;
}
diff --git a/drivers/gpu/drm/tegra/plane.h b/drivers/gpu/drm/tegra/plane.h
index dfb20712fbd7..e33a581e6490 100644
--- a/drivers/gpu/drm/tegra/plane.h
+++ b/drivers/gpu/drm/tegra/plane.h
@@ -90,7 +90,7 @@ int tegra_plane_state_add(struct tegra_plane *plane,
int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap);
bool tegra_plane_format_is_indexed(unsigned int format);
-bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *bpc);
+bool tegra_plane_format_is_yuv(unsigned int format, unsigned int *planes, unsigned int *bpc);
int tegra_plane_setup_legacy_state(struct tegra_plane *tegra,
struct tegra_plane_state *state);
int tegra_plane_interconnect_init(struct tegra_plane *plane);
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 0ea320c1092b..b125572feb84 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -18,7 +18,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_debugfs.h>
-#include <drm/drm_dp_helper.h>
+#include <drm/dp/drm_dp_helper.h>
#include <drm/drm_file.h>
#include <drm/drm_panel.h>
#include <drm/drm_scdc_helper.h>