Commit 66a8af1f authored by Dave Airlie's avatar Dave Airlie

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: default avatarDave 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
parents 38a15ad9 cf5086d3
...@@ -345,18 +345,19 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, ...@@ -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; unsigned h_offset, v_offset, h_size, v_size, h_dda, v_dda, bpp;
struct tegra_dc *dc = plane->dc; struct tegra_dc *dc = plane->dc;
bool yuv, planar; unsigned int planes;
u32 value; u32 value;
bool yuv;
/* /*
* For YUV planar modes, the number of bytes per pixel takes into * For YUV planar modes, the number of bytes per pixel takes into
* account only the luma component and therefore is 1. * 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) if (!yuv)
bpp = window->bits_per_pixel / 8; bpp = window->bits_per_pixel / 8;
else 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->format, DC_WIN_COLOR_DEPTH);
tegra_plane_writel(plane, window->swap, DC_WIN_BYTE_SWAP); tegra_plane_writel(plane, window->swap, DC_WIN_BYTE_SWAP);
...@@ -385,7 +386,7 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, ...@@ -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 * For DDA computations the number of bytes per pixel for YUV planar
* modes needs to take into account all Y, U and V components. * modes needs to take into account all Y, U and V components.
*/ */
if (yuv && planar) if (yuv && planes > 1)
bpp = 2; bpp = 2;
h_dda = compute_dda_inc(window->src.w, window->dst.w, false, bpp); 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, ...@@ -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); 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[1], DC_WINBUF_START_ADDR_U);
if (planes > 2)
tegra_plane_writel(plane, window->base[2], DC_WINBUF_START_ADDR_V); tegra_plane_writel(plane, window->base[2], DC_WINBUF_START_ADDR_V);
value = window->stride[1] << 16 | window->stride[0]; value = window->stride[1] << 16 | window->stride[0];
tegra_plane_writel(plane, value, DC_WIN_LINE_STRIDE); tegra_plane_writel(plane, value, DC_WIN_LINE_STRIDE);
} else { } else {
...@@ -1193,6 +1197,13 @@ static const u32 tegra114_overlay_formats[] = { ...@@ -1193,6 +1197,13 @@ static const u32 tegra114_overlay_formats[] = {
DRM_FORMAT_YUYV, DRM_FORMAT_YUYV,
DRM_FORMAT_YUV420, DRM_FORMAT_YUV420,
DRM_FORMAT_YUV422, 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[] = { static const u32 tegra124_overlay_formats[] = {
...@@ -1221,8 +1232,18 @@ static const u32 tegra124_overlay_formats[] = { ...@@ -1221,8 +1232,18 @@ static const u32 tegra124_overlay_formats[] = {
/* planar formats */ /* planar formats */
DRM_FORMAT_UYVY, DRM_FORMAT_UYVY,
DRM_FORMAT_YUYV, DRM_FORMAT_YUYV,
DRM_FORMAT_YUV420, DRM_FORMAT_YVYU,
DRM_FORMAT_YUV422, 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, 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) ...@@ -3211,16 +3232,9 @@ static int tegra_dc_probe(struct platform_device *pdev)
return -ENXIO; return -ENXIO;
err = tegra_dc_rgb_probe(dc); err = tegra_dc_rgb_probe(dc);
if (err < 0 && err != -ENODEV) { if (err < 0 && err != -ENODEV)
const char *level = KERN_ERR; return dev_err_probe(&pdev->dev, err,
"failed to probe RGB output\n");
if (err == -EPROBE_DEFER)
level = KERN_DEBUG;
dev_printk(level, dc->dev, "failed to probe RGB output: %d\n",
err);
return err;
}
platform_set_drvdata(pdev, dc); platform_set_drvdata(pdev, dc);
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
......
...@@ -637,6 +637,13 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc); ...@@ -637,6 +637,13 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
#define WIN_COLOR_DEPTH_A8B8G8R8 36 #define WIN_COLOR_DEPTH_A8B8G8R8 36
#define WIN_COLOR_DEPTH_B8G8R8X8 37 #define WIN_COLOR_DEPTH_B8G8R8X8 37
#define WIN_COLOR_DEPTH_R8G8B8X8 38 #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_X8B8G8R8 65
#define WIN_COLOR_DEPTH_X8R8G8B8 66 #define WIN_COLOR_DEPTH_X8R8G8B8 66
......
...@@ -280,7 +280,6 @@ static void tegra_dpaux_hotplug(struct work_struct *work) ...@@ -280,7 +280,6 @@ static void tegra_dpaux_hotplug(struct work_struct *work)
static irqreturn_t tegra_dpaux_irq(int irq, void *data) static irqreturn_t tegra_dpaux_irq(int irq, void *data)
{ {
struct tegra_dpaux *dpaux = data; struct tegra_dpaux *dpaux = data;
irqreturn_t ret = IRQ_HANDLED;
u32 value; u32 value;
/* clear interrupts */ /* clear interrupts */
...@@ -297,7 +296,7 @@ static irqreturn_t tegra_dpaux_irq(int irq, void *data) ...@@ -297,7 +296,7 @@ static irqreturn_t tegra_dpaux_irq(int irq, void *data)
if (value & DPAUX_INTR_AUX_DONE) if (value & DPAUX_INTR_AUX_DONE)
complete(&dpaux->complete); complete(&dpaux->complete);
return ret; return IRQ_HANDLED;
} }
enum tegra_dpaux_functions { enum tegra_dpaux_functions {
......
...@@ -1538,8 +1538,10 @@ static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi) ...@@ -1538,8 +1538,10 @@ static int tegra_dsi_ganged_probe(struct tegra_dsi *dsi)
dsi->slave = platform_get_drvdata(gangster); dsi->slave = platform_get_drvdata(gangster);
of_node_put(np); of_node_put(np);
if (!dsi->slave) if (!dsi->slave) {
put_device(&gangster->dev);
return -EPROBE_DEFER; return -EPROBE_DEFER;
}
dsi->slave->master = dsi; dsi->slave->master = dsi;
} }
......
...@@ -1775,7 +1775,6 @@ static irqreturn_t tegra_hdmi_irq(int irq, void *data) ...@@ -1775,7 +1775,6 @@ static irqreturn_t tegra_hdmi_irq(int irq, void *data)
static int tegra_hdmi_probe(struct platform_device *pdev) static int tegra_hdmi_probe(struct platform_device *pdev)
{ {
const char *level = KERN_ERR;
struct tegra_hdmi *hdmi; struct tegra_hdmi *hdmi;
struct resource *regs; struct resource *regs;
int err; int err;
...@@ -1817,36 +1816,21 @@ static int tegra_hdmi_probe(struct platform_device *pdev) ...@@ -1817,36 +1816,21 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
hdmi->hdmi = devm_regulator_get(&pdev->dev, "hdmi"); hdmi->hdmi = devm_regulator_get(&pdev->dev, "hdmi");
err = PTR_ERR_OR_ZERO(hdmi->hdmi); err = PTR_ERR_OR_ZERO(hdmi->hdmi);
if (err) { if (err)
if (err == -EPROBE_DEFER) return dev_err_probe(&pdev->dev, err,
level = KERN_DEBUG; "failed to get HDMI regulator\n");
dev_printk(level, &pdev->dev,
"failed to get HDMI regulator: %d\n", err);
return err;
}
hdmi->pll = devm_regulator_get(&pdev->dev, "pll"); hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
err = PTR_ERR_OR_ZERO(hdmi->pll); err = PTR_ERR_OR_ZERO(hdmi->pll);
if (err) { if (err)
if (err == -EPROBE_DEFER) return dev_err_probe(&pdev->dev, err,
level = KERN_DEBUG; "failed to get PLL regulator\n");
dev_printk(level, &pdev->dev,
"failed to get PLL regulator: %d\n", err);
return err;
}
hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd"); hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
err = PTR_ERR_OR_ZERO(hdmi->vdd); err = PTR_ERR_OR_ZERO(hdmi->vdd);
if (err) { if (err)
if (err == -EPROBE_DEFER) return dev_err_probe(&pdev->dev, err,
level = KERN_DEBUG; "failed to get VDD regulator\n");
dev_printk(level, &pdev->dev,
"failed to get VDD regulator: %d\n", err);
return err;
}
hdmi->output.dev = &pdev->dev; hdmi->output.dev = &pdev->dev;
......
...@@ -540,8 +540,8 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, ...@@ -540,8 +540,8 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
struct tegra_plane *p = to_tegra_plane(plane); struct tegra_plane *p = to_tegra_plane(plane);
u32 value, min_width, bypass = 0; u32 value, min_width, bypass = 0;
dma_addr_t base, addr_flag = 0; dma_addr_t base, addr_flag = 0;
unsigned int bpc; unsigned int bpc, planes;
bool yuv, planar; bool yuv;
int err; int err;
/* rien ne va plus */ /* rien ne va plus */
...@@ -559,7 +559,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, ...@@ -559,7 +559,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
return; 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); tegra_dc_assign_shared_plane(dc, p);
...@@ -660,20 +660,26 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, ...@@ -660,20 +660,26 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
value = PITCH(fb->pitches[0]); value = PITCH(fb->pitches[0]);
tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE); 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 = tegra_plane_state->iova[1] + fb->offsets[1];
base |= addr_flag; base |= addr_flag;
tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_U); 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); tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_U);
if (planes > 2) {
base = tegra_plane_state->iova[2] + fb->offsets[2]; base = tegra_plane_state->iova[2] + fb->offsets[2];
base |= addr_flag; base |= addr_flag;
tegra_plane_writel(p, upper_32_bits(base), DC_WINBUF_START_ADDR_HI_V); 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); tegra_plane_writel(p, lower_32_bits(base), DC_WINBUF_START_ADDR_V);
}
value = PITCH_U(fb->pitches[1]);
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); tegra_plane_writel(p, value, DC_WIN_PLANAR_STORAGE_UV);
} else { } else {
tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_U); tegra_plane_writel(p, 0, DC_WINBUF_START_ADDR_U);
......
...@@ -413,6 +413,22 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap) ...@@ -413,6 +413,22 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
*swap = BYTE_SWAP_SWAP2; *swap = BYTE_SWAP_SWAP2;
break; 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: case DRM_FORMAT_YUV420:
*format = WIN_COLOR_DEPTH_YCbCr420P; *format = WIN_COLOR_DEPTH_YCbCr420P;
break; break;
...@@ -421,6 +437,34 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap) ...@@ -421,6 +437,34 @@ int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap)
*format = WIN_COLOR_DEPTH_YCbCr422P; *format = WIN_COLOR_DEPTH_YCbCr422P;
break; 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: default:
return -EINVAL; return -EINVAL;
} }
...@@ -441,13 +485,13 @@ bool tegra_plane_format_is_indexed(unsigned int format) ...@@ -441,13 +485,13 @@ bool tegra_plane_format_is_indexed(unsigned int format)
return false; 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) { switch (format) {
case WIN_COLOR_DEPTH_YCbCr422: case WIN_COLOR_DEPTH_YCbCr422:
case WIN_COLOR_DEPTH_YUV422: case WIN_COLOR_DEPTH_YUV422:
if (planar) if (planes)
*planar = false; *planes = 1;
if (bpc) if (bpc)
*bpc = 8; *bpc = 8;
...@@ -462,8 +506,23 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int * ...@@ -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_YUV422R:
case WIN_COLOR_DEPTH_YCbCr422RA: case WIN_COLOR_DEPTH_YCbCr422RA:
case WIN_COLOR_DEPTH_YUV422RA: case WIN_COLOR_DEPTH_YUV422RA:
if (planar) case WIN_COLOR_DEPTH_YCbCr444P:
*planar = true; 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) if (bpc)
*bpc = 8; *bpc = 8;
...@@ -471,8 +530,8 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int * ...@@ -471,8 +530,8 @@ bool tegra_plane_format_is_yuv(unsigned int format, bool *planar, unsigned int *
return true; return true;
} }
if (planar) if (planes)
*planar = false; *planes = 1;
return false; return false;
} }
......
...@@ -90,7 +90,7 @@ int tegra_plane_state_add(struct tegra_plane *plane, ...@@ -90,7 +90,7 @@ int tegra_plane_state_add(struct tegra_plane *plane,
int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap); int tegra_plane_format(u32 fourcc, u32 *format, u32 *swap);
bool tegra_plane_format_is_indexed(unsigned int format); 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, int tegra_plane_setup_legacy_state(struct tegra_plane *tegra,
struct tegra_plane_state *state); struct tegra_plane_state *state);
int tegra_plane_interconnect_init(struct tegra_plane *plane); int tegra_plane_interconnect_init(struct tegra_plane *plane);
......
...@@ -447,7 +447,6 @@ static int host1x_probe(struct platform_device *pdev) ...@@ -447,7 +447,6 @@ static int host1x_probe(struct platform_device *pdev)
if (syncpt_irq < 0) if (syncpt_irq < 0)
return syncpt_irq; return syncpt_irq;
host1x_bo_cache_init(&host->cache);
mutex_init(&host->devices_lock); mutex_init(&host->devices_lock);
INIT_LIST_HEAD(&host->devices); INIT_LIST_HEAD(&host->devices);
INIT_LIST_HEAD(&host->list); INIT_LIST_HEAD(&host->list);
...@@ -489,10 +488,12 @@ static int host1x_probe(struct platform_device *pdev) ...@@ -489,10 +488,12 @@ static int host1x_probe(struct platform_device *pdev)
if (err) if (err)
return err; return err;
host1x_bo_cache_init(&host->cache);
err = host1x_iommu_init(host); err = host1x_iommu_init(host);
if (err < 0) { if (err < 0) {
dev_err(&pdev->dev, "failed to setup IOMMU: %d\n", err); dev_err(&pdev->dev, "failed to setup IOMMU: %d\n", err);
return err; goto destroy_cache;
} }
err = host1x_channel_list_init(&host->channel_list, err = host1x_channel_list_init(&host->channel_list,
...@@ -553,6 +554,8 @@ static int host1x_probe(struct platform_device *pdev) ...@@ -553,6 +554,8 @@ static int host1x_probe(struct platform_device *pdev)
host1x_channel_list_free(&host->channel_list); host1x_channel_list_free(&host->channel_list);
iommu_exit: iommu_exit:
host1x_iommu_exit(host); host1x_iommu_exit(host);
destroy_cache:
host1x_bo_cache_destroy(&host->cache);
return err; return err;
} }
...@@ -568,6 +571,7 @@ static int host1x_remove(struct platform_device *pdev) ...@@ -568,6 +571,7 @@ static int host1x_remove(struct platform_device *pdev)
host1x_intr_deinit(host); host1x_intr_deinit(host);
host1x_syncpt_deinit(host); host1x_syncpt_deinit(host);
host1x_channel_list_free(&host->channel_list);
host1x_iommu_exit(host); host1x_iommu_exit(host);
host1x_bo_cache_destroy(&host->cache); host1x_bo_cache_destroy(&host->cache);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment