summaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/st/stm32/dma2d/dma2d-hw.c
blob: ea4cc84d8a391c39948c5ac75f06d152c5ba1da5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * ST stm32 Chrom-Art - 2D Graphics Accelerator Driver
 *
 * Copyright (c) 2021 Dillon Min
 * Dillon Min, <dillon.minfei@gmail.com>
 *
 * based on s5p-g2d
 *
 * Copyright (c) 2011 Samsung Electronics Co., Ltd.
 * Kamil Debski, <k.debski@samsung.com>
 */

#include <linux/io.h>

#include "dma2d.h"
#include "dma2d-regs.h"

static inline u32 reg_read(void __iomem *base, u32 reg)
{
	return readl_relaxed(base + reg);
}

static inline void reg_write(void __iomem *base, u32 reg, u32 val)
{
	writel_relaxed(val, base + reg);
}

static inline void reg_update_bits(void __iomem *base, u32 reg, u32 mask,
				   u32 val)
{
	reg_write(base, reg, (reg_read(base, reg) & ~mask) | val);
}

void dma2d_start(struct dma2d_dev *d)
{
	reg_update_bits(d->regs, DMA2D_CR_REG, CR_START, CR_START);
}

u32 dma2d_get_int(struct dma2d_dev *d)
{
	return reg_read(d->regs, DMA2D_ISR_REG);
}

void dma2d_clear_int(struct dma2d_dev *d)
{
	u32 isr_val = reg_read(d->regs, DMA2D_ISR_REG);

	reg_write(d->regs, DMA2D_IFCR_REG, isr_val & 0x003f);
}

void dma2d_config_common(struct dma2d_dev *d, enum dma2d_op_mode op_mode,
			 u16 width, u16 height)
{
	reg_update_bits(d->regs, DMA2D_CR_REG, CR_MODE_MASK,
			op_mode << CR_MODE_SHIFT);

	reg_write(d->regs, DMA2D_NLR_REG, (width << 16) | height);
}

void dma2d_config_out(struct dma2d_dev *d, struct dma2d_frame *frm,
		      dma_addr_t o_addr)
{
	reg_update_bits(d->regs, DMA2D_CR_REG, CR_CEIE, CR_CEIE);
	reg_update_bits(d->regs, DMA2D_CR_REG, CR_CTCIE, CR_CTCIE);
	reg_update_bits(d->regs, DMA2D_CR_REG, CR_CAEIE, CR_CAEIE);
	reg_update_bits(d->regs, DMA2D_CR_REG, CR_TCIE, CR_TCIE);
	reg_update_bits(d->regs, DMA2D_CR_REG, CR_TEIE, CR_TEIE);

	if (frm->fmt->cmode >= CM_MODE_ARGB8888 &&
	    frm->fmt->cmode <= CM_MODE_ARGB4444)
		reg_update_bits(d->regs, DMA2D_OPFCCR_REG, OPFCCR_CM_MASK,
				frm->fmt->cmode);

	reg_write(d->regs, DMA2D_OMAR_REG, o_addr);

	reg_write(d->regs, DMA2D_OCOLR_REG,
		  (frm->a_rgb[3] << 24) |
		  (frm->a_rgb[2] << 16) |
		  (frm->a_rgb[1] << 8) |
		  frm->a_rgb[0]);

	reg_update_bits(d->regs, DMA2D_OOR_REG, OOR_LO_MASK,
			frm->line_offset & 0x3fff);
}

void dma2d_config_fg(struct dma2d_dev *d, struct dma2d_frame *frm,
		     dma_addr_t f_addr)
{
	reg_write(d->regs, DMA2D_FGMAR_REG, f_addr);
	reg_update_bits(d->regs, DMA2D_FGOR_REG, FGOR_LO_MASK,
			frm->line_offset);

	if (frm->fmt->cmode >= CM_MODE_ARGB8888 &&
	    frm->fmt->cmode <= CM_MODE_A4)
		reg_update_bits(d->regs, DMA2D_FGPFCCR_REG, FGPFCCR_CM_MASK,
				frm->fmt->cmode);

	reg_update_bits(d->regs, DMA2D_FGPFCCR_REG, FGPFCCR_AM_MASK,
			(frm->a_mode << 16) & 0x03);

	reg_update_bits(d->regs, DMA2D_FGPFCCR_REG, FGPFCCR_ALPHA_MASK,
			frm->a_rgb[3] << 24);

	reg_write(d->regs, DMA2D_FGCOLR_REG,
		  (frm->a_rgb[2] << 16) |
		  (frm->a_rgb[1] << 8) |
		  frm->a_rgb[0]);
}

void dma2d_config_bg(struct dma2d_dev *d, struct dma2d_frame *frm,
		     dma_addr_t b_addr)
{
	reg_write(d->regs, DMA2D_BGMAR_REG, b_addr);
	reg_update_bits(d->regs, DMA2D_BGOR_REG, BGOR_LO_MASK,
			frm->line_offset);

	if (frm->fmt->cmode >= CM_MODE_ARGB8888 &&
	    frm->fmt->cmode <= CM_MODE_A4)
		reg_update_bits(d->regs, DMA2D_BGPFCCR_REG, BGPFCCR_CM_MASK,
				frm->fmt->cmode);

	reg_update_bits(d->regs, DMA2D_BGPFCCR_REG, BGPFCCR_AM_MASK,
			(frm->a_mode << 16) & 0x03);

	reg_update_bits(d->regs, DMA2D_BGPFCCR_REG, BGPFCCR_ALPHA_MASK,
			frm->a_rgb[3] << 24);

	reg_write(d->regs, DMA2D_BGCOLR_REG,
		  (frm->a_rgb[2] << 16) |
		  (frm->a_rgb[1] << 8) |
		  frm->a_rgb[0]);
}