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

shmob_drm_plane.c (7046B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * shmob_drm_plane.c  --  SH Mobile DRM Planes
      4 *
      5 * Copyright (C) 2012 Renesas Electronics Corporation
      6 *
      7 * Laurent Pinchart (laurent.pinchart@ideasonboard.com)
      8 */
      9
     10#include <drm/drm_crtc.h>
     11#include <drm/drm_crtc_helper.h>
     12#include <drm/drm_fb_cma_helper.h>
     13#include <drm/drm_fourcc.h>
     14#include <drm/drm_gem_cma_helper.h>
     15
     16#include "shmob_drm_drv.h"
     17#include "shmob_drm_kms.h"
     18#include "shmob_drm_plane.h"
     19#include "shmob_drm_regs.h"
     20
     21struct shmob_drm_plane {
     22	struct drm_plane plane;
     23	unsigned int index;
     24	unsigned int alpha;
     25
     26	const struct shmob_drm_format_info *format;
     27	unsigned long dma[2];
     28
     29	unsigned int src_x;
     30	unsigned int src_y;
     31	unsigned int crtc_x;
     32	unsigned int crtc_y;
     33	unsigned int crtc_w;
     34	unsigned int crtc_h;
     35};
     36
     37#define to_shmob_plane(p)	container_of(p, struct shmob_drm_plane, plane)
     38
     39static void shmob_drm_plane_compute_base(struct shmob_drm_plane *splane,
     40					 struct drm_framebuffer *fb,
     41					 int x, int y)
     42{
     43	struct drm_gem_cma_object *gem;
     44	unsigned int bpp;
     45
     46	bpp = splane->format->yuv ? 8 : splane->format->bpp;
     47	gem = drm_fb_cma_get_gem_obj(fb, 0);
     48	splane->dma[0] = gem->paddr + fb->offsets[0]
     49		       + y * fb->pitches[0] + x * bpp / 8;
     50
     51	if (splane->format->yuv) {
     52		bpp = splane->format->bpp - 8;
     53		gem = drm_fb_cma_get_gem_obj(fb, 1);
     54		splane->dma[1] = gem->paddr + fb->offsets[1]
     55			       + y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
     56			       + x * (bpp == 16 ? 2 : 1);
     57	}
     58}
     59
     60static void __shmob_drm_plane_setup(struct shmob_drm_plane *splane,
     61				    struct drm_framebuffer *fb)
     62{
     63	struct shmob_drm_device *sdev = splane->plane.dev->dev_private;
     64	u32 format;
     65
     66	/* TODO: Support ROP3 mode */
     67	format = LDBBSIFR_EN | (splane->alpha << LDBBSIFR_LAY_SHIFT);
     68
     69	switch (splane->format->fourcc) {
     70	case DRM_FORMAT_RGB565:
     71	case DRM_FORMAT_NV21:
     72	case DRM_FORMAT_NV61:
     73	case DRM_FORMAT_NV42:
     74		format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW;
     75		break;
     76	case DRM_FORMAT_RGB888:
     77	case DRM_FORMAT_NV12:
     78	case DRM_FORMAT_NV16:
     79	case DRM_FORMAT_NV24:
     80		format |= LDBBSIFR_SWPL | LDBBSIFR_SWPW | LDBBSIFR_SWPB;
     81		break;
     82	case DRM_FORMAT_ARGB8888:
     83	default:
     84		format |= LDBBSIFR_SWPL;
     85		break;
     86	}
     87
     88	switch (splane->format->fourcc) {
     89	case DRM_FORMAT_RGB565:
     90		format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB16;
     91		break;
     92	case DRM_FORMAT_RGB888:
     93		format |= LDBBSIFR_AL_1 | LDBBSIFR_RY | LDBBSIFR_RPKF_RGB24;
     94		break;
     95	case DRM_FORMAT_ARGB8888:
     96		format |= LDBBSIFR_AL_PK | LDBBSIFR_RY | LDDFR_PKF_ARGB32;
     97		break;
     98	case DRM_FORMAT_NV12:
     99	case DRM_FORMAT_NV21:
    100		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_420;
    101		break;
    102	case DRM_FORMAT_NV16:
    103	case DRM_FORMAT_NV61:
    104		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_422;
    105		break;
    106	case DRM_FORMAT_NV24:
    107	case DRM_FORMAT_NV42:
    108		format |= LDBBSIFR_AL_1 | LDBBSIFR_CHRR_444;
    109		break;
    110	}
    111
    112#define plane_reg_dump(sdev, splane, reg) \
    113	dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x 0x%08x\n", __func__, \
    114		splane->index, #reg, \
    115		lcdc_read(sdev, reg(splane->index)), \
    116		lcdc_read(sdev, reg(splane->index) + LCDC_SIDE_B_OFFSET))
    117
    118	plane_reg_dump(sdev, splane, LDBnBSIFR);
    119	plane_reg_dump(sdev, splane, LDBnBSSZR);
    120	plane_reg_dump(sdev, splane, LDBnBLOCR);
    121	plane_reg_dump(sdev, splane, LDBnBSMWR);
    122	plane_reg_dump(sdev, splane, LDBnBSAYR);
    123	plane_reg_dump(sdev, splane, LDBnBSACR);
    124
    125	lcdc_write(sdev, LDBCR, LDBCR_UPC(splane->index));
    126	dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
    127		"LDBCR", lcdc_read(sdev, LDBCR));
    128
    129	lcdc_write(sdev, LDBnBSIFR(splane->index), format);
    130
    131	lcdc_write(sdev, LDBnBSSZR(splane->index),
    132		   (splane->crtc_h << LDBBSSZR_BVSS_SHIFT) |
    133		   (splane->crtc_w << LDBBSSZR_BHSS_SHIFT));
    134	lcdc_write(sdev, LDBnBLOCR(splane->index),
    135		   (splane->crtc_y << LDBBLOCR_CVLC_SHIFT) |
    136		   (splane->crtc_x << LDBBLOCR_CHLC_SHIFT));
    137	lcdc_write(sdev, LDBnBSMWR(splane->index),
    138		   fb->pitches[0] << LDBBSMWR_BSMW_SHIFT);
    139
    140	shmob_drm_plane_compute_base(splane, fb, splane->src_x, splane->src_y);
    141
    142	lcdc_write(sdev, LDBnBSAYR(splane->index), splane->dma[0]);
    143	if (splane->format->yuv)
    144		lcdc_write(sdev, LDBnBSACR(splane->index), splane->dma[1]);
    145
    146	lcdc_write(sdev, LDBCR,
    147		   LDBCR_UPF(splane->index) | LDBCR_UPD(splane->index));
    148	dev_dbg(sdev->ddev->dev, "%s(%u): %s 0x%08x\n", __func__, splane->index,
    149		"LDBCR", lcdc_read(sdev, LDBCR));
    150
    151	plane_reg_dump(sdev, splane, LDBnBSIFR);
    152	plane_reg_dump(sdev, splane, LDBnBSSZR);
    153	plane_reg_dump(sdev, splane, LDBnBLOCR);
    154	plane_reg_dump(sdev, splane, LDBnBSMWR);
    155	plane_reg_dump(sdev, splane, LDBnBSAYR);
    156	plane_reg_dump(sdev, splane, LDBnBSACR);
    157}
    158
    159void shmob_drm_plane_setup(struct drm_plane *plane)
    160{
    161	struct shmob_drm_plane *splane = to_shmob_plane(plane);
    162
    163	if (plane->fb == NULL)
    164		return;
    165
    166	__shmob_drm_plane_setup(splane, plane->fb);
    167}
    168
    169static int
    170shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
    171		       struct drm_framebuffer *fb, int crtc_x, int crtc_y,
    172		       unsigned int crtc_w, unsigned int crtc_h,
    173		       uint32_t src_x, uint32_t src_y,
    174		       uint32_t src_w, uint32_t src_h,
    175		       struct drm_modeset_acquire_ctx *ctx)
    176{
    177	struct shmob_drm_plane *splane = to_shmob_plane(plane);
    178	struct shmob_drm_device *sdev = plane->dev->dev_private;
    179	const struct shmob_drm_format_info *format;
    180
    181	format = shmob_drm_format_info(fb->format->format);
    182	if (format == NULL) {
    183		dev_dbg(sdev->dev, "update_plane: unsupported format %08x\n",
    184			fb->format->format);
    185		return -EINVAL;
    186	}
    187
    188	if (src_w >> 16 != crtc_w || src_h >> 16 != crtc_h) {
    189		dev_dbg(sdev->dev, "%s: scaling not supported\n", __func__);
    190		return -EINVAL;
    191	}
    192
    193	splane->format = format;
    194
    195	splane->src_x = src_x >> 16;
    196	splane->src_y = src_y >> 16;
    197	splane->crtc_x = crtc_x;
    198	splane->crtc_y = crtc_y;
    199	splane->crtc_w = crtc_w;
    200	splane->crtc_h = crtc_h;
    201
    202	__shmob_drm_plane_setup(splane, fb);
    203	return 0;
    204}
    205
    206static int shmob_drm_plane_disable(struct drm_plane *plane,
    207				   struct drm_modeset_acquire_ctx *ctx)
    208{
    209	struct shmob_drm_plane *splane = to_shmob_plane(plane);
    210	struct shmob_drm_device *sdev = plane->dev->dev_private;
    211
    212	splane->format = NULL;
    213
    214	lcdc_write(sdev, LDBnBSIFR(splane->index), 0);
    215	return 0;
    216}
    217
    218static void shmob_drm_plane_destroy(struct drm_plane *plane)
    219{
    220	drm_plane_force_disable(plane);
    221	drm_plane_cleanup(plane);
    222}
    223
    224static const struct drm_plane_funcs shmob_drm_plane_funcs = {
    225	.update_plane = shmob_drm_plane_update,
    226	.disable_plane = shmob_drm_plane_disable,
    227	.destroy = shmob_drm_plane_destroy,
    228};
    229
    230static const uint32_t formats[] = {
    231	DRM_FORMAT_RGB565,
    232	DRM_FORMAT_RGB888,
    233	DRM_FORMAT_ARGB8888,
    234	DRM_FORMAT_NV12,
    235	DRM_FORMAT_NV21,
    236	DRM_FORMAT_NV16,
    237	DRM_FORMAT_NV61,
    238	DRM_FORMAT_NV24,
    239	DRM_FORMAT_NV42,
    240};
    241
    242int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index)
    243{
    244	struct shmob_drm_plane *splane;
    245	int ret;
    246
    247	splane = devm_kzalloc(sdev->dev, sizeof(*splane), GFP_KERNEL);
    248	if (splane == NULL)
    249		return -ENOMEM;
    250
    251	splane->index = index;
    252	splane->alpha = 255;
    253
    254	ret = drm_plane_init(sdev->ddev, &splane->plane, 1,
    255			     &shmob_drm_plane_funcs, formats,
    256			     ARRAY_SIZE(formats), false);
    257
    258	return ret;
    259}