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

sti_vid.c (6004B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) STMicroelectronics SA 2014
      4 * Author: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
      5 */
      6#include <linux/seq_file.h>
      7
      8#include <drm/drm_debugfs.h>
      9#include <drm/drm_file.h>
     10#include <drm/drm_print.h>
     11
     12#include "sti_plane.h"
     13#include "sti_vid.h"
     14#include "sti_vtg.h"
     15
     16/* Registers */
     17#define VID_CTL                 0x00
     18#define VID_ALP                 0x04
     19#define VID_CLF                 0x08
     20#define VID_VPO                 0x0C
     21#define VID_VPS                 0x10
     22#define VID_KEY1                0x28
     23#define VID_KEY2                0x2C
     24#define VID_MPR0                0x30
     25#define VID_MPR1                0x34
     26#define VID_MPR2                0x38
     27#define VID_MPR3                0x3C
     28#define VID_MST                 0x68
     29#define VID_BC                  0x70
     30#define VID_TINT                0x74
     31#define VID_CSAT                0x78
     32
     33/* Registers values */
     34#define VID_CTL_IGNORE          (BIT(31) | BIT(30))
     35#define VID_CTL_PSI_ENABLE      (BIT(2) | BIT(1) | BIT(0))
     36#define VID_ALP_OPAQUE          0x00000080
     37#define VID_BC_DFLT             0x00008000
     38#define VID_TINT_DFLT           0x00000000
     39#define VID_CSAT_DFLT           0x00000080
     40/* YCbCr to RGB BT709:
     41 * R = Y+1.5391Cr
     42 * G = Y-0.4590Cr-0.1826Cb
     43 * B = Y+1.8125Cb */
     44#define VID_MPR0_BT709          0x0A800000
     45#define VID_MPR1_BT709          0x0AC50000
     46#define VID_MPR2_BT709          0x07150545
     47#define VID_MPR3_BT709          0x00000AE8
     48/* YCbCr to RGB BT709:
     49 * R = Y+1.3711Cr
     50 * G = Y-0.6992Cr-0.3359Cb
     51 * B = Y+1.7344Cb
     52 */
     53#define VID_MPR0_BT601          0x0A800000
     54#define VID_MPR1_BT601          0x0AAF0000
     55#define VID_MPR2_BT601          0x094E0754
     56#define VID_MPR3_BT601          0x00000ADD
     57
     58#define VID_MIN_HD_HEIGHT       720
     59
     60#define DBGFS_DUMP(reg) seq_printf(s, "\n  %-25s 0x%08X", #reg, \
     61				   readl(vid->regs + reg))
     62
     63static void vid_dbg_ctl(struct seq_file *s, int val)
     64{
     65	val = val >> 30;
     66	seq_putc(s, '\t');
     67
     68	if (!(val & 1))
     69		seq_puts(s, "NOT ");
     70	seq_puts(s, "ignored on main mixer - ");
     71
     72	if (!(val & 2))
     73		seq_puts(s, "NOT ");
     74	seq_puts(s, "ignored on aux mixer");
     75}
     76
     77static void vid_dbg_vpo(struct seq_file *s, int val)
     78{
     79	seq_printf(s, "\txdo:%4d\tydo:%4d", val & 0x0FFF, (val >> 16) & 0x0FFF);
     80}
     81
     82static void vid_dbg_vps(struct seq_file *s, int val)
     83{
     84	seq_printf(s, "\txds:%4d\tyds:%4d", val & 0x0FFF, (val >> 16) & 0x0FFF);
     85}
     86
     87static void vid_dbg_mst(struct seq_file *s, int val)
     88{
     89	if (val & 1)
     90		seq_puts(s, "\tBUFFER UNDERFLOW!");
     91}
     92
     93static int vid_dbg_show(struct seq_file *s, void *arg)
     94{
     95	struct drm_info_node *node = s->private;
     96	struct sti_vid *vid = (struct sti_vid *)node->info_ent->data;
     97
     98	seq_printf(s, "VID: (vaddr= 0x%p)", vid->regs);
     99
    100	DBGFS_DUMP(VID_CTL);
    101	vid_dbg_ctl(s, readl(vid->regs + VID_CTL));
    102	DBGFS_DUMP(VID_ALP);
    103	DBGFS_DUMP(VID_CLF);
    104	DBGFS_DUMP(VID_VPO);
    105	vid_dbg_vpo(s, readl(vid->regs + VID_VPO));
    106	DBGFS_DUMP(VID_VPS);
    107	vid_dbg_vps(s, readl(vid->regs + VID_VPS));
    108	DBGFS_DUMP(VID_KEY1);
    109	DBGFS_DUMP(VID_KEY2);
    110	DBGFS_DUMP(VID_MPR0);
    111	DBGFS_DUMP(VID_MPR1);
    112	DBGFS_DUMP(VID_MPR2);
    113	DBGFS_DUMP(VID_MPR3);
    114	DBGFS_DUMP(VID_MST);
    115	vid_dbg_mst(s, readl(vid->regs + VID_MST));
    116	DBGFS_DUMP(VID_BC);
    117	DBGFS_DUMP(VID_TINT);
    118	DBGFS_DUMP(VID_CSAT);
    119	seq_putc(s, '\n');
    120	return 0;
    121}
    122
    123static struct drm_info_list vid_debugfs_files[] = {
    124	{ "vid", vid_dbg_show, 0, NULL },
    125};
    126
    127void vid_debugfs_init(struct sti_vid *vid, struct drm_minor *minor)
    128{
    129	unsigned int i;
    130
    131	for (i = 0; i < ARRAY_SIZE(vid_debugfs_files); i++)
    132		vid_debugfs_files[i].data = vid;
    133
    134	drm_debugfs_create_files(vid_debugfs_files,
    135				 ARRAY_SIZE(vid_debugfs_files),
    136				 minor->debugfs_root, minor);
    137}
    138
    139void sti_vid_commit(struct sti_vid *vid,
    140		    struct drm_plane_state *state)
    141{
    142	struct drm_crtc *crtc = state->crtc;
    143	struct drm_display_mode *mode = &crtc->mode;
    144	int dst_x = state->crtc_x;
    145	int dst_y = state->crtc_y;
    146	int dst_w = clamp_val(state->crtc_w, 0, mode->hdisplay - dst_x);
    147	int dst_h = clamp_val(state->crtc_h, 0, mode->vdisplay - dst_y);
    148	int src_h = state->src_h >> 16;
    149	u32 val, ydo, xdo, yds, xds;
    150
    151	/* Input / output size
    152	 * Align to upper even value */
    153	dst_w = ALIGN(dst_w, 2);
    154	dst_h = ALIGN(dst_h, 2);
    155
    156	/* Unmask */
    157	val = readl(vid->regs + VID_CTL);
    158	val &= ~VID_CTL_IGNORE;
    159	writel(val, vid->regs + VID_CTL);
    160
    161	ydo = sti_vtg_get_line_number(*mode, dst_y);
    162	yds = sti_vtg_get_line_number(*mode, dst_y + dst_h - 1);
    163	xdo = sti_vtg_get_pixel_number(*mode, dst_x);
    164	xds = sti_vtg_get_pixel_number(*mode, dst_x + dst_w - 1);
    165
    166	writel((ydo << 16) | xdo, vid->regs + VID_VPO);
    167	writel((yds << 16) | xds, vid->regs + VID_VPS);
    168
    169	/* Color conversion parameters */
    170	if (src_h >= VID_MIN_HD_HEIGHT) {
    171		writel(VID_MPR0_BT709, vid->regs + VID_MPR0);
    172		writel(VID_MPR1_BT709, vid->regs + VID_MPR1);
    173		writel(VID_MPR2_BT709, vid->regs + VID_MPR2);
    174		writel(VID_MPR3_BT709, vid->regs + VID_MPR3);
    175	} else {
    176		writel(VID_MPR0_BT601, vid->regs + VID_MPR0);
    177		writel(VID_MPR1_BT601, vid->regs + VID_MPR1);
    178		writel(VID_MPR2_BT601, vid->regs + VID_MPR2);
    179		writel(VID_MPR3_BT601, vid->regs + VID_MPR3);
    180	}
    181}
    182
    183void sti_vid_disable(struct sti_vid *vid)
    184{
    185	u32 val;
    186
    187	/* Mask */
    188	val = readl(vid->regs + VID_CTL);
    189	val |= VID_CTL_IGNORE;
    190	writel(val, vid->regs + VID_CTL);
    191}
    192
    193static void sti_vid_init(struct sti_vid *vid)
    194{
    195	/* Enable PSI, Mask layer */
    196	writel(VID_CTL_PSI_ENABLE | VID_CTL_IGNORE, vid->regs + VID_CTL);
    197
    198	/* Opaque */
    199	writel(VID_ALP_OPAQUE, vid->regs + VID_ALP);
    200
    201	/* Brightness, contrast, tint, saturation */
    202	writel(VID_BC_DFLT, vid->regs + VID_BC);
    203	writel(VID_TINT_DFLT, vid->regs + VID_TINT);
    204	writel(VID_CSAT_DFLT, vid->regs + VID_CSAT);
    205}
    206
    207struct sti_vid *sti_vid_create(struct device *dev, struct drm_device *drm_dev,
    208			       int id, void __iomem *baseaddr)
    209{
    210	struct sti_vid *vid;
    211
    212	vid = devm_kzalloc(dev, sizeof(*vid), GFP_KERNEL);
    213	if (!vid) {
    214		DRM_ERROR("Failed to allocate memory for VID\n");
    215		return NULL;
    216	}
    217
    218	vid->dev = dev;
    219	vid->regs = baseaddr;
    220	vid->id = id;
    221
    222	sti_vid_init(vid);
    223
    224	return vid;
    225}