diff options
author | Dave Airlie <airlied@redhat.com> | 2022-03-04 12:50:47 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2022-03-04 12:50:56 +1000 |
commit | 66a8af1f6e3c10190dff14a5668661c092a2a85f (patch) | |
tree | 6049df8b2b2eec4a951bacee21d7a1c833681d0b /drivers/gpu/drm/tegra | |
parent | 38a15ad9488e21cad8f42d3befca20f91e5b2874 (diff) | |
parent | cf5086d35d8c7c2b9cb1ca34590097a5f2f8b588 (diff) | |
download | linux-66a8af1f6e3c10190dff14a5668661c092a2a85f.tar.gz |
Merge tag 'drm/tegra/for-5.18-rc1' of https://gitlab.freedesktop.org/drm/tegra into drm-next
drm/tegra: Changes for v5.18-rc1
This contains a couple more minor fixes that didn't seem urgent enough
for v5.17. On top of that this improves YUV format support on older
chips.
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thierry Reding <thierry.reding@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220301124426.1207653-1-thierry.reding@gmail.com
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 50 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 7 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dpaux.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dsi.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/hdmi.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/hub.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/plane.c | 73 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/plane.h | 2 |
8 files changed, 134 insertions, 63 deletions
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/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 5847dcad2478..20e1dd6b3bf0 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -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/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/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); |