cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tve200_display.c (10187B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
      4 * Parts of this file were based on sources as follows:
      5 *
      6 * Copyright (C) 2006-2008 Intel Corporation
      7 * Copyright (C) 2007 Amos Lee <amos_lee@storlinksemi.com>
      8 * Copyright (C) 2007 Dave Airlie <airlied@linux.ie>
      9 * Copyright (C) 2011 Texas Instruments
     10 * Copyright (C) 2017 Eric Anholt
     11 */
     12
     13#include <linux/clk.h>
     14#include <linux/dma-buf.h>
     15#include <linux/of_graph.h>
     16#include <linux/delay.h>
     17
     18#include <drm/drm_fb_cma_helper.h>
     19#include <drm/drm_fourcc.h>
     20#include <drm/drm_gem_atomic_helper.h>
     21#include <drm/drm_gem_cma_helper.h>
     22#include <drm/drm_panel.h>
     23#include <drm/drm_vblank.h>
     24
     25#include "tve200_drm.h"
     26
     27irqreturn_t tve200_irq(int irq, void *data)
     28{
     29	struct tve200_drm_dev_private *priv = data;
     30	u32 stat;
     31	u32 val;
     32
     33	stat = readl(priv->regs + TVE200_INT_STAT);
     34
     35	if (!stat)
     36		return IRQ_NONE;
     37
     38	/*
     39	 * Vblank IRQ
     40	 *
     41	 * The hardware is a bit tilted: the line stays high after clearing
     42	 * the vblank IRQ, firing many more interrupts. We counter this
     43	 * by toggling the IRQ back and forth from firing at vblank and
     44	 * firing at start of active image, which works around the problem
     45	 * since those occur strictly in sequence, and we get two IRQs for each
     46	 * frame, one at start of Vblank (that we make call into the CRTC) and
     47	 * another one at the start of the image (that we discard).
     48	 */
     49	if (stat & TVE200_INT_V_STATUS) {
     50		val = readl(priv->regs + TVE200_CTRL);
     51		/* We have an actual start of vsync */
     52		if (!(val & TVE200_VSTSTYPE_BITS)) {
     53			drm_crtc_handle_vblank(&priv->pipe.crtc);
     54			/* Toggle trigger to start of active image */
     55			val |= TVE200_VSTSTYPE_VAI;
     56		} else {
     57			/* Toggle trigger back to start of vsync */
     58			val &= ~TVE200_VSTSTYPE_BITS;
     59		}
     60		writel(val, priv->regs + TVE200_CTRL);
     61	} else
     62		dev_err(priv->drm->dev, "stray IRQ %08x\n", stat);
     63
     64	/* Clear the interrupt once done */
     65	writel(stat, priv->regs + TVE200_INT_CLR);
     66
     67	return IRQ_HANDLED;
     68}
     69
     70static int tve200_display_check(struct drm_simple_display_pipe *pipe,
     71			       struct drm_plane_state *pstate,
     72			       struct drm_crtc_state *cstate)
     73{
     74	const struct drm_display_mode *mode = &cstate->mode;
     75	struct drm_framebuffer *old_fb = pipe->plane.state->fb;
     76	struct drm_framebuffer *fb = pstate->fb;
     77
     78	/*
     79	 * We support these specific resolutions and nothing else.
     80	 */
     81	if (!(mode->hdisplay == 352 && mode->vdisplay == 240) && /* SIF(525) */
     82	    !(mode->hdisplay == 352 && mode->vdisplay == 288) && /* CIF(625) */
     83	    !(mode->hdisplay == 640 && mode->vdisplay == 480) && /* VGA */
     84	    !(mode->hdisplay == 720 && mode->vdisplay == 480) && /* D1 */
     85	    !(mode->hdisplay == 720 && mode->vdisplay == 576)) { /* D1 */
     86		DRM_DEBUG_KMS("unsupported display mode (%u x %u)\n",
     87			mode->hdisplay, mode->vdisplay);
     88		return -EINVAL;
     89	}
     90
     91	if (fb) {
     92		u32 offset = drm_fb_cma_get_gem_addr(fb, pstate, 0);
     93
     94		/* FB base address must be dword aligned. */
     95		if (offset & 3) {
     96			DRM_DEBUG_KMS("FB not 32-bit aligned\n");
     97			return -EINVAL;
     98		}
     99
    100		/*
    101		 * There's no pitch register, the mode's hdisplay
    102		 * controls this.
    103		 */
    104		if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) {
    105			DRM_DEBUG_KMS("can't handle pitches\n");
    106			return -EINVAL;
    107		}
    108
    109		/*
    110		 * We can't change the FB format in a flicker-free
    111		 * manner (and only update it during CRTC enable).
    112		 */
    113		if (old_fb && old_fb->format != fb->format)
    114			cstate->mode_changed = true;
    115	}
    116
    117	return 0;
    118}
    119
    120static void tve200_display_enable(struct drm_simple_display_pipe *pipe,
    121				 struct drm_crtc_state *cstate,
    122				 struct drm_plane_state *plane_state)
    123{
    124	struct drm_crtc *crtc = &pipe->crtc;
    125	struct drm_plane *plane = &pipe->plane;
    126	struct drm_device *drm = crtc->dev;
    127	struct tve200_drm_dev_private *priv = drm->dev_private;
    128	const struct drm_display_mode *mode = &cstate->mode;
    129	struct drm_framebuffer *fb = plane->state->fb;
    130	struct drm_connector *connector = priv->connector;
    131	u32 format = fb->format->format;
    132	u32 ctrl1 = 0;
    133	int retries;
    134
    135	clk_prepare_enable(priv->clk);
    136
    137	/* Reset the TVE200 and wait for it to come back online */
    138	writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4);
    139	for (retries = 0; retries < 5; retries++) {
    140		usleep_range(30000, 50000);
    141		if (readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET)
    142			continue;
    143		else
    144			break;
    145	}
    146	if (retries == 5 &&
    147	    readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET) {
    148		dev_err(drm->dev, "can't get hardware out of reset\n");
    149		return;
    150	}
    151
    152	/* Function 1 */
    153	ctrl1 |= TVE200_CTRL_CSMODE;
    154	/* Interlace mode for CCIR656: parameterize? */
    155	ctrl1 |= TVE200_CTRL_NONINTERLACE;
    156	/* 32 words per burst */
    157	ctrl1 |= TVE200_CTRL_BURST_32_WORDS;
    158	/* 16 retries */
    159	ctrl1 |= TVE200_CTRL_RETRYCNT_16;
    160	/* NTSC mode: parametrize? */
    161	ctrl1 |= TVE200_CTRL_NTSC;
    162
    163	/* Vsync IRQ at start of Vsync at first */
    164	ctrl1 |= TVE200_VSTSTYPE_VSYNC;
    165
    166	if (connector->display_info.bus_flags &
    167	    DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE)
    168		ctrl1 |= TVE200_CTRL_TVCLKP;
    169
    170	if ((mode->hdisplay == 352 && mode->vdisplay == 240) || /* SIF(525) */
    171	    (mode->hdisplay == 352 && mode->vdisplay == 288)) { /* CIF(625) */
    172		ctrl1 |= TVE200_CTRL_IPRESOL_CIF;
    173		dev_info(drm->dev, "CIF mode\n");
    174	} else if (mode->hdisplay == 640 && mode->vdisplay == 480) {
    175		ctrl1 |= TVE200_CTRL_IPRESOL_VGA;
    176		dev_info(drm->dev, "VGA mode\n");
    177	} else if ((mode->hdisplay == 720 && mode->vdisplay == 480) ||
    178		   (mode->hdisplay == 720 && mode->vdisplay == 576)) {
    179		ctrl1 |= TVE200_CTRL_IPRESOL_D1;
    180		dev_info(drm->dev, "D1 mode\n");
    181	}
    182
    183	if (format & DRM_FORMAT_BIG_ENDIAN) {
    184		ctrl1 |= TVE200_CTRL_BBBP;
    185		format &= ~DRM_FORMAT_BIG_ENDIAN;
    186	}
    187
    188	switch (format) {
    189	case DRM_FORMAT_XRGB8888:
    190		ctrl1 |= TVE200_IPDMOD_RGB888;
    191		break;
    192	case DRM_FORMAT_RGB565:
    193		ctrl1 |= TVE200_IPDMOD_RGB565;
    194		break;
    195	case DRM_FORMAT_XRGB1555:
    196		ctrl1 |= TVE200_IPDMOD_RGB555;
    197		break;
    198	case DRM_FORMAT_XBGR8888:
    199		ctrl1 |= TVE200_IPDMOD_RGB888 | TVE200_BGR;
    200		break;
    201	case DRM_FORMAT_BGR565:
    202		ctrl1 |= TVE200_IPDMOD_RGB565 | TVE200_BGR;
    203		break;
    204	case DRM_FORMAT_XBGR1555:
    205		ctrl1 |= TVE200_IPDMOD_RGB555 | TVE200_BGR;
    206		break;
    207	case DRM_FORMAT_YUYV:
    208		ctrl1 |= TVE200_IPDMOD_YUV422;
    209		ctrl1 |= TVE200_CTRL_YCBCRODR_CR0Y1CB0Y0;
    210		break;
    211	case DRM_FORMAT_YVYU:
    212		ctrl1 |= TVE200_IPDMOD_YUV422;
    213		ctrl1 |= TVE200_CTRL_YCBCRODR_CB0Y1CR0Y0;
    214		break;
    215	case DRM_FORMAT_UYVY:
    216		ctrl1 |= TVE200_IPDMOD_YUV422;
    217		ctrl1 |= TVE200_CTRL_YCBCRODR_Y1CR0Y0CB0;
    218		break;
    219	case DRM_FORMAT_VYUY:
    220		ctrl1 |= TVE200_IPDMOD_YUV422;
    221		ctrl1 |= TVE200_CTRL_YCBCRODR_Y1CB0Y0CR0;
    222		break;
    223	case DRM_FORMAT_YUV420:
    224		ctrl1 |= TVE200_CTRL_YUV420;
    225		ctrl1 |= TVE200_IPDMOD_YUV420;
    226		break;
    227	default:
    228		dev_err(drm->dev, "Unknown FB format 0x%08x\n",
    229			fb->format->format);
    230		break;
    231	}
    232
    233	ctrl1 |= TVE200_TVEEN;
    234
    235	/* Turn it on */
    236	writel(ctrl1, priv->regs + TVE200_CTRL);
    237
    238	drm_crtc_vblank_on(crtc);
    239}
    240
    241static void tve200_display_disable(struct drm_simple_display_pipe *pipe)
    242{
    243	struct drm_crtc *crtc = &pipe->crtc;
    244	struct drm_device *drm = crtc->dev;
    245	struct tve200_drm_dev_private *priv = drm->dev_private;
    246
    247	drm_crtc_vblank_off(crtc);
    248
    249	/* Disable put into reset and Power Down */
    250	writel(0, priv->regs + TVE200_CTRL);
    251	writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4);
    252
    253	clk_disable_unprepare(priv->clk);
    254}
    255
    256static void tve200_display_update(struct drm_simple_display_pipe *pipe,
    257				 struct drm_plane_state *old_pstate)
    258{
    259	struct drm_crtc *crtc = &pipe->crtc;
    260	struct drm_device *drm = crtc->dev;
    261	struct tve200_drm_dev_private *priv = drm->dev_private;
    262	struct drm_pending_vblank_event *event = crtc->state->event;
    263	struct drm_plane *plane = &pipe->plane;
    264	struct drm_plane_state *pstate = plane->state;
    265	struct drm_framebuffer *fb = pstate->fb;
    266
    267	if (fb) {
    268		/* For RGB, the Y component is used as base address */
    269		writel(drm_fb_cma_get_gem_addr(fb, pstate, 0),
    270		       priv->regs + TVE200_Y_FRAME_BASE_ADDR);
    271
    272		/* For three plane YUV we need two more addresses */
    273		if (fb->format->format == DRM_FORMAT_YUV420) {
    274			writel(drm_fb_cma_get_gem_addr(fb, pstate, 1),
    275			       priv->regs + TVE200_U_FRAME_BASE_ADDR);
    276			writel(drm_fb_cma_get_gem_addr(fb, pstate, 2),
    277			       priv->regs + TVE200_V_FRAME_BASE_ADDR);
    278		}
    279	}
    280
    281	if (event) {
    282		crtc->state->event = NULL;
    283
    284		spin_lock_irq(&crtc->dev->event_lock);
    285		if (crtc->state->active && drm_crtc_vblank_get(crtc) == 0)
    286			drm_crtc_arm_vblank_event(crtc, event);
    287		else
    288			drm_crtc_send_vblank_event(crtc, event);
    289		spin_unlock_irq(&crtc->dev->event_lock);
    290	}
    291}
    292
    293static int tve200_display_enable_vblank(struct drm_simple_display_pipe *pipe)
    294{
    295	struct drm_crtc *crtc = &pipe->crtc;
    296	struct drm_device *drm = crtc->dev;
    297	struct tve200_drm_dev_private *priv = drm->dev_private;
    298
    299	/* Clear any IRQs and enable */
    300	writel(0xFF, priv->regs + TVE200_INT_CLR);
    301	writel(TVE200_INT_V_STATUS, priv->regs + TVE200_INT_EN);
    302	return 0;
    303}
    304
    305static void tve200_display_disable_vblank(struct drm_simple_display_pipe *pipe)
    306{
    307	struct drm_crtc *crtc = &pipe->crtc;
    308	struct drm_device *drm = crtc->dev;
    309	struct tve200_drm_dev_private *priv = drm->dev_private;
    310
    311	writel(0, priv->regs + TVE200_INT_EN);
    312}
    313
    314static const struct drm_simple_display_pipe_funcs tve200_display_funcs = {
    315	.check = tve200_display_check,
    316	.enable = tve200_display_enable,
    317	.disable = tve200_display_disable,
    318	.update = tve200_display_update,
    319	.enable_vblank = tve200_display_enable_vblank,
    320	.disable_vblank = tve200_display_disable_vblank,
    321};
    322
    323int tve200_display_init(struct drm_device *drm)
    324{
    325	struct tve200_drm_dev_private *priv = drm->dev_private;
    326	int ret;
    327	static const u32 formats[] = {
    328		DRM_FORMAT_XRGB8888,
    329		DRM_FORMAT_XBGR8888,
    330		DRM_FORMAT_RGB565,
    331		DRM_FORMAT_BGR565,
    332		DRM_FORMAT_XRGB1555,
    333		DRM_FORMAT_XBGR1555,
    334		/*
    335		 * The controller actually supports any YCbCr ordering,
    336		 * for packed YCbCr. This just lists the orderings that
    337		 * DRM supports.
    338		 */
    339		DRM_FORMAT_YUYV,
    340		DRM_FORMAT_YVYU,
    341		DRM_FORMAT_UYVY,
    342		DRM_FORMAT_VYUY,
    343		/* This uses three planes */
    344		DRM_FORMAT_YUV420,
    345	};
    346
    347	ret = drm_simple_display_pipe_init(drm, &priv->pipe,
    348					   &tve200_display_funcs,
    349					   formats, ARRAY_SIZE(formats),
    350					   NULL,
    351					   priv->connector);
    352	if (ret)
    353		return ret;
    354
    355	return 0;
    356}