Skip to content

Commit

Permalink
Merge tag 'drm/tegra/for-5.18-rc1' of https://gitlab.freedesktop.org/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Dave Airlie committed Mar 4, 2022
2 parents 38a15ad + cf5086d commit 66a8af1
Showing 9 changed files with 140 additions and 65 deletions.
50 changes: 32 additions & 18 deletions drivers/gpu/drm/tegra/dc.c
Original file line number Diff line number Diff line change
@@ -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);
7 changes: 7 additions & 0 deletions drivers/gpu/drm/tegra/dc.h
Original file line number Diff line number Diff line change
@@ -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

3 changes: 1 addition & 2 deletions drivers/gpu/drm/tegra/dpaux.c
Original file line number Diff line number Diff line change
@@ -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 {
4 changes: 3 additions & 1 deletion drivers/gpu/drm/tegra/dsi.c
Original file line number Diff line number Diff line change
@@ -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;
}
34 changes: 9 additions & 25 deletions drivers/gpu/drm/tegra/hdmi.c
Original file line number Diff line number Diff line change
@@ -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;

24 changes: 15 additions & 9 deletions drivers/gpu/drm/tegra/hub.c
Original file line number Diff line number Diff line change
@@ -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);
73 changes: 66 additions & 7 deletions drivers/gpu/drm/tegra/plane.c
Original file line number Diff line number Diff line change
@@ -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,17 +506,32 @@ 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;

return true;
}

if (planar)
*planar = false;
if (planes)
*planes = 1;

return false;
}
2 changes: 1 addition & 1 deletion drivers/gpu/drm/tegra/plane.h
Original file line number Diff line number Diff line change
@@ -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);
Loading

0 comments on commit 66a8af1

Please sign in to comment.