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

dpu_hw_lm.c (6255B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
      4 */
      5
      6#include "dpu_kms.h"
      7#include "dpu_hw_catalog.h"
      8#include "dpu_hwio.h"
      9#include "dpu_hw_lm.h"
     10#include "dpu_hw_mdss.h"
     11
     12#define LM_OP_MODE                        0x00
     13#define LM_OUT_SIZE                       0x04
     14#define LM_BORDER_COLOR_0                 0x08
     15#define LM_BORDER_COLOR_1                 0x010
     16
     17/* These register are offset to mixer base + stage base */
     18#define LM_BLEND0_OP                     0x00
     19#define LM_BLEND0_CONST_ALPHA            0x04
     20#define LM_FG_COLOR_FILL_COLOR_0         0x08
     21#define LM_FG_COLOR_FILL_COLOR_1         0x0C
     22#define LM_FG_COLOR_FILL_SIZE            0x10
     23#define LM_FG_COLOR_FILL_XY              0x14
     24
     25#define LM_BLEND0_FG_ALPHA               0x04
     26#define LM_BLEND0_BG_ALPHA               0x08
     27
     28#define LM_MISR_CTRL                     0x310
     29#define LM_MISR_SIGNATURE                0x314
     30#define LM_MISR_FRAME_COUNT_MASK         0xFF
     31#define LM_MISR_CTRL_ENABLE              BIT(8)
     32#define LM_MISR_CTRL_STATUS              BIT(9)
     33#define LM_MISR_CTRL_STATUS_CLEAR        BIT(10)
     34#define LM_MISR_CTRL_FREE_RUN_MASK     BIT(31)
     35
     36
     37static const struct dpu_lm_cfg *_lm_offset(enum dpu_lm mixer,
     38		const struct dpu_mdss_cfg *m,
     39		void __iomem *addr,
     40		struct dpu_hw_blk_reg_map *b)
     41{
     42	int i;
     43
     44	for (i = 0; i < m->mixer_count; i++) {
     45		if (mixer == m->mixer[i].id) {
     46			b->base_off = addr;
     47			b->blk_off = m->mixer[i].base;
     48			b->length = m->mixer[i].len;
     49			b->hwversion = m->hwversion;
     50			b->log_mask = DPU_DBG_MASK_LM;
     51			return &m->mixer[i];
     52		}
     53	}
     54
     55	return ERR_PTR(-ENOMEM);
     56}
     57
     58/**
     59 * _stage_offset(): returns the relative offset of the blend registers
     60 * for the stage to be setup
     61 * @ctx:     mixer ctx contains the mixer to be programmed
     62 * @stage: stage index to setup
     63 */
     64static inline int _stage_offset(struct dpu_hw_mixer *ctx, enum dpu_stage stage)
     65{
     66	const struct dpu_lm_sub_blks *sblk = ctx->cap->sblk;
     67	if (stage != DPU_STAGE_BASE && stage <= sblk->maxblendstages)
     68		return sblk->blendstage_base[stage - DPU_STAGE_0];
     69
     70	return -EINVAL;
     71}
     72
     73static void dpu_hw_lm_setup_out(struct dpu_hw_mixer *ctx,
     74		struct dpu_hw_mixer_cfg *mixer)
     75{
     76	struct dpu_hw_blk_reg_map *c = &ctx->hw;
     77	u32 outsize;
     78	u32 op_mode;
     79
     80	op_mode = DPU_REG_READ(c, LM_OP_MODE);
     81
     82	outsize = mixer->out_height << 16 | mixer->out_width;
     83	DPU_REG_WRITE(c, LM_OUT_SIZE, outsize);
     84
     85	/* SPLIT_LEFT_RIGHT */
     86	if (mixer->right_mixer)
     87		op_mode |= BIT(31);
     88	else
     89		op_mode &= ~BIT(31);
     90	DPU_REG_WRITE(c, LM_OP_MODE, op_mode);
     91}
     92
     93static void dpu_hw_lm_setup_border_color(struct dpu_hw_mixer *ctx,
     94		struct dpu_mdss_color *color,
     95		u8 border_en)
     96{
     97	struct dpu_hw_blk_reg_map *c = &ctx->hw;
     98
     99	if (border_en) {
    100		DPU_REG_WRITE(c, LM_BORDER_COLOR_0,
    101			(color->color_0 & 0xFFF) |
    102			((color->color_1 & 0xFFF) << 0x10));
    103		DPU_REG_WRITE(c, LM_BORDER_COLOR_1,
    104			(color->color_2 & 0xFFF) |
    105			((color->color_3 & 0xFFF) << 0x10));
    106	}
    107}
    108
    109static void dpu_hw_lm_setup_misr(struct dpu_hw_mixer *ctx, bool enable, u32 frame_count)
    110{
    111	struct dpu_hw_blk_reg_map *c = &ctx->hw;
    112	u32 config = 0;
    113
    114	DPU_REG_WRITE(c, LM_MISR_CTRL, LM_MISR_CTRL_STATUS_CLEAR);
    115
    116	/* Clear old MISR value (in case it's read before a new value is calculated)*/
    117	wmb();
    118
    119	if (enable) {
    120		config = (frame_count & LM_MISR_FRAME_COUNT_MASK) |
    121			LM_MISR_CTRL_ENABLE | LM_MISR_CTRL_FREE_RUN_MASK;
    122
    123		DPU_REG_WRITE(c, LM_MISR_CTRL, config);
    124	} else {
    125		DPU_REG_WRITE(c, LM_MISR_CTRL, 0);
    126	}
    127
    128}
    129
    130static int dpu_hw_lm_collect_misr(struct dpu_hw_mixer *ctx, u32 *misr_value)
    131{
    132	struct dpu_hw_blk_reg_map *c = &ctx->hw;
    133	u32 ctrl = 0;
    134
    135	if (!misr_value)
    136		return -EINVAL;
    137
    138	ctrl = DPU_REG_READ(c, LM_MISR_CTRL);
    139
    140	if (!(ctrl & LM_MISR_CTRL_ENABLE))
    141		return -ENODATA;
    142
    143	if (!(ctrl & LM_MISR_CTRL_STATUS))
    144		return -EINVAL;
    145
    146	*misr_value = DPU_REG_READ(c, LM_MISR_SIGNATURE);
    147
    148	return 0;
    149}
    150
    151static void dpu_hw_lm_setup_blend_config_sdm845(struct dpu_hw_mixer *ctx,
    152	u32 stage, u32 fg_alpha, u32 bg_alpha, u32 blend_op)
    153{
    154	struct dpu_hw_blk_reg_map *c = &ctx->hw;
    155	int stage_off;
    156	u32 const_alpha;
    157
    158	if (stage == DPU_STAGE_BASE)
    159		return;
    160
    161	stage_off = _stage_offset(ctx, stage);
    162	if (WARN_ON(stage_off < 0))
    163		return;
    164
    165	const_alpha = (bg_alpha & 0xFF) | ((fg_alpha & 0xFF) << 16);
    166	DPU_REG_WRITE(c, LM_BLEND0_CONST_ALPHA + stage_off, const_alpha);
    167	DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op);
    168}
    169
    170static void dpu_hw_lm_setup_blend_config(struct dpu_hw_mixer *ctx,
    171	u32 stage, u32 fg_alpha, u32 bg_alpha, u32 blend_op)
    172{
    173	struct dpu_hw_blk_reg_map *c = &ctx->hw;
    174	int stage_off;
    175
    176	if (stage == DPU_STAGE_BASE)
    177		return;
    178
    179	stage_off = _stage_offset(ctx, stage);
    180	if (WARN_ON(stage_off < 0))
    181		return;
    182
    183	DPU_REG_WRITE(c, LM_BLEND0_FG_ALPHA + stage_off, fg_alpha);
    184	DPU_REG_WRITE(c, LM_BLEND0_BG_ALPHA + stage_off, bg_alpha);
    185	DPU_REG_WRITE(c, LM_BLEND0_OP + stage_off, blend_op);
    186}
    187
    188static void dpu_hw_lm_setup_color3(struct dpu_hw_mixer *ctx,
    189	uint32_t mixer_op_mode)
    190{
    191	struct dpu_hw_blk_reg_map *c = &ctx->hw;
    192	int op_mode;
    193
    194	/* read the existing op_mode configuration */
    195	op_mode = DPU_REG_READ(c, LM_OP_MODE);
    196
    197	op_mode = (op_mode & (BIT(31) | BIT(30))) | mixer_op_mode;
    198
    199	DPU_REG_WRITE(c, LM_OP_MODE, op_mode);
    200}
    201
    202static void _setup_mixer_ops(const struct dpu_mdss_cfg *m,
    203		struct dpu_hw_lm_ops *ops,
    204		unsigned long features)
    205{
    206	ops->setup_mixer_out = dpu_hw_lm_setup_out;
    207	if (m->hwversion >= DPU_HW_VER_400)
    208		ops->setup_blend_config = dpu_hw_lm_setup_blend_config_sdm845;
    209	else
    210		ops->setup_blend_config = dpu_hw_lm_setup_blend_config;
    211	ops->setup_alpha_out = dpu_hw_lm_setup_color3;
    212	ops->setup_border_color = dpu_hw_lm_setup_border_color;
    213	ops->setup_misr = dpu_hw_lm_setup_misr;
    214	ops->collect_misr = dpu_hw_lm_collect_misr;
    215}
    216
    217struct dpu_hw_mixer *dpu_hw_lm_init(enum dpu_lm idx,
    218		void __iomem *addr,
    219		const struct dpu_mdss_cfg *m)
    220{
    221	struct dpu_hw_mixer *c;
    222	const struct dpu_lm_cfg *cfg;
    223
    224	c = kzalloc(sizeof(*c), GFP_KERNEL);
    225	if (!c)
    226		return ERR_PTR(-ENOMEM);
    227
    228	cfg = _lm_offset(idx, m, addr, &c->hw);
    229	if (IS_ERR_OR_NULL(cfg)) {
    230		kfree(c);
    231		return ERR_PTR(-EINVAL);
    232	}
    233
    234	/* Assign ops */
    235	c->idx = idx;
    236	c->cap = cfg;
    237	_setup_mixer_ops(m, &c->ops, c->cap->features);
    238
    239	return c;
    240}
    241
    242void dpu_hw_lm_destroy(struct dpu_hw_mixer *lm)
    243{
    244	kfree(lm);
    245}