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,
{
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);
......
......@@ -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
......
......@@ -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 {
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -447,7 +447,6 @@ static int host1x_probe(struct platform_device *pdev)
if (syncpt_irq < 0)
return syncpt_irq;
host1x_bo_cache_init(&host->cache);
mutex_init(&host->devices_lock);
INIT_LIST_HEAD(&host->devices);
INIT_LIST_HEAD(&host->list);
......@@ -489,10 +488,12 @@ static int host1x_probe(struct platform_device *pdev)
if (err)
return err;
host1x_bo_cache_init(&host->cache);
err = host1x_iommu_init(host);
if (err < 0) {
dev_err(&pdev->dev, "failed to setup IOMMU: %d\n", err);
return err;
goto destroy_cache;
}
err = host1x_channel_list_init(&host->channel_list,
......@@ -553,6 +554,8 @@ static int host1x_probe(struct platform_device *pdev)
host1x_channel_list_free(&host->channel_list);
iommu_exit:
host1x_iommu_exit(host);
destroy_cache:
host1x_bo_cache_destroy(&host->cache);
return err;
}
......@@ -568,6 +571,7 @@ static int host1x_remove(struct platform_device *pdev)
host1x_intr_deinit(host);
host1x_syncpt_deinit(host);
host1x_channel_list_free(&host->channel_list);
host1x_iommu_exit(host);
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