// SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. */ #include #include "dpu_hw_mdss.h" #include "dpu_hwio.h" #include "dpu_hw_catalog.h" #include "dpu_hw_merge3d.h" #include "dpu_kms.h" #include "dpu_trace.h" #define MERGE_3D_MUX 0x000 #define MERGE_3D_MODE 0x004 static const struct dpu_merge_3d_cfg *_merge_3d_offset(enum dpu_merge_3d idx, const struct dpu_mdss_cfg *m, void __iomem *addr, struct dpu_hw_blk_reg_map *b) { int i; for (i = 0; i < m->merge_3d_count; i++) { if (idx == m->merge_3d[i].id) { b->base_off = addr; b->blk_off = m->merge_3d[i].base; b->length = m->merge_3d[i].len; b->hwversion = m->hwversion; b->log_mask = DPU_DBG_MASK_PINGPONG; return &m->merge_3d[i]; } } return ERR_PTR(-EINVAL); } static void dpu_hw_merge_3d_setup_3d_mode(struct dpu_hw_merge_3d *merge_3d, enum dpu_3d_blend_mode mode_3d) { struct dpu_hw_blk_reg_map *c; u32 data; c = &merge_3d->hw; if (mode_3d == BLEND_3D_NONE) { DPU_REG_WRITE(c, MERGE_3D_MODE, 0); DPU_REG_WRITE(c, MERGE_3D_MUX, 0); } else { data = BIT(0) | ((mode_3d - 1) << 1); DPU_REG_WRITE(c, MERGE_3D_MODE, data); } } static void _setup_merge_3d_ops(struct dpu_hw_merge_3d *c, unsigned long features) { c->ops.setup_3d_mode = dpu_hw_merge_3d_setup_3d_mode; }; struct dpu_hw_merge_3d *dpu_hw_merge_3d_init(enum dpu_merge_3d idx, void __iomem *addr, const struct dpu_mdss_cfg *m) { struct dpu_hw_merge_3d *c; const struct dpu_merge_3d_cfg *cfg; c = kzalloc(sizeof(*c), GFP_KERNEL); if (!c) return ERR_PTR(-ENOMEM); cfg = _merge_3d_offset(idx, m, addr, &c->hw); if (IS_ERR_OR_NULL(cfg)) { kfree(c); return ERR_PTR(-EINVAL); } c->idx = idx; c->caps = cfg; _setup_merge_3d_ops(c, c->caps->features); return c; } void dpu_hw_merge_3d_destroy(struct dpu_hw_merge_3d *hw) { kfree(hw); }