embox

Форк
0
275 строк · 7.5 Кб
1
/**
2
 * @file ipuv3.c
3
 * @brief Probe/irq handle/reset/channel init/etc
4
 * @date Sep 15, 2017
5
 * @author Anton Bondarev
6
 */
7

8
#include <util/log.h>
9

10
#include <string.h>
11
#include <assert.h>
12

13
#include <hal/reg.h>
14
#include <drivers/common/memory.h>
15
#include <drivers/video/fb.h>
16
#include <drivers/clk/ccm_imx6.h>
17
#include <kernel/irq.h>
18

19
#include "ipu_regs.h"
20
#include "ipu_priv.h"
21
#include "ipu_param_mem.h"
22

23
extern void _ipu_dc_init(struct ipu_soc *ipu, int dc_chan, int di, bool interlaced, uint32_t pixel_fmt);
24
extern void _ipu_dc_uninit(struct ipu_soc *ipu, int dc_chan);
25
extern void _ipu_init_dc_mappings(struct ipu_soc *ipu);
26
extern void _ipu_dp_dc_enable(struct ipu_soc *ipu, ipu_channel_t channel);
27

28
static struct ipu_soc ipu_soc;
29

30
#define idma_mask(ch)		(1UL << (ch & 0x1F))
31
#define idma_is_set(ipu, reg, dma)	(ipu_idmac_read(ipu, reg(dma)) & idma_mask(dma))
32

33
/**
34
 * @brief Perform software reset for all IPU modules
35
 */
36
static void ipu_reset(void) {
37
#define SRC_BASE 0x20D8000
38
# define SRC_IPU_RESET (1 << 3)
39
	REG32_ORIN(SRC_BASE, SRC_IPU_RESET);
40
	int timeout=0xfffff;
41
	while(timeout--) {
42
		if (!(REG32_LOAD(SRC_BASE) & SRC_IPU_RESET)) {
43
			break;
44
		}
45
	}
46

47
	if (timeout == 0) {
48
		log_error("IPU reset timeout!\n");
49
	} else {
50
		log_debug("IPU reset ok!\n");
51
	}
52
}
53

54
static int ipu_mem_reset(struct ipu_soc *ipu) {
55
	int i = 1000000;
56

57
	ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
58

59
	while (i-- > 0) {
60
		if (!(ipu_cm_read(ipu, IPU_MEM_RST) & (1u << 31)))
61
			break;
62
	}
63

64
	if (i <= 0) {
65
		log_error("Failed to reset IPU internal memories");
66
	}
67

68
	return 0;
69
}
70

71
struct ipu_soc *ipu_get() {
72
	return &ipu_soc;
73
}
74

75
int ipu_probe(void) {
76
	struct ipu_soc *ipu = ipu_get();
77

78
	clk_enable("ipu1");
79
	memset(ipu, 0, sizeof(struct ipu_soc));
80

81
	ipu->cm_reg		= (void*) IPU_BASE + IPU_CM_REG_BASE;
82
	ipu->ic_reg		= (void*) IPU_BASE + IPU_IC_REG_BASE;
83
	ipu->idmac_reg		= (void*) IPU_BASE + IPU_IDMAC_REG_BASE;
84
	ipu->dp_reg		= (void*) IPU_BASE + IPU_SRM_REG_BASE;
85
	ipu->dc_reg		= (void*) IPU_BASE + IPU_DC_REG_BASE;
86
	ipu->dmfc_reg		= (void*) IPU_BASE + IPU_DMFC_REG_BASE;
87
	ipu->di_reg[0]		= (void*) IPU_BASE + IPU_DI0_REG_BASE;
88
	ipu->di_reg[1]		= (void*) IPU_BASE + IPU_DI1_REG_BASE;
89
	ipu->smfc_reg		= (void*) IPU_BASE + IPU_SMFC_REG_BASE;
90
	ipu->cpmem_base		= (void*) IPU_BASE + IPU_CPMEM_REG_BASE;
91
	ipu->tpmem_base		= (void*) IPU_BASE + IPU_TPM_REG_BASE;
92
	ipu->dc_tmpl_reg	= (void*) IPU_BASE + IPU_DC_TMPL_REG_BASE;
93
	ipu->vdi_reg		= (void*) IPU_BASE + IPU_VDI_REG_BASE;
94
	ipu->disp_base[1]	= (void*) IPU_BASE + IPU_DISP1_BASE;
95

96
	ipu_reset();
97

98
	/* Disable all channels */
99
	ipu_idmac_write(ipu, 0x0, IDMAC_WM_EN(0));
100
	ipu_idmac_write(ipu, 0x0, IDMAC_WM_EN(32));
101

102
	ipu_idmac_write(ipu, 0x0, IDMAC_WM_EN(0));
103
	ipu_idmac_write(ipu, 0x0, IDMAC_WM_EN(32));
104

105
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_CHA_CUR_BUF(0));
106
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_CHA_CUR_BUF(32));
107

108
	ipu_cm_write(ipu, 0x0, IPU_CHA_DB_MODE_SEL(0));
109
	ipu_cm_write(ipu, 0x0, IPU_CHA_DB_MODE_SEL(32));
110

111
	memset((void*) ipu->cpmem_base, 0, IPU_CPMEM_REG_LEN);
112

113
	clk_enable("ipu1");
114
	clk_enable("ipu1_di0");
115
	clk_enable("ldb_di0");
116

117
	ipu_mem_reset(ipu);
118

119
	_ipu_init_dc_mappings(ipu);
120

121
	/* Enable error interrupts by default */
122
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(5));
123
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(6));
124
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(9));
125
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(10));
126

127
	return 0;
128
}
129

130
int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params) {
131
	/* note: assume channel is MEM_BG_SYNC
132
	 *       assume DI=0			*/
133
	log_debug("init channel = %d", IPU_CHAN_VIDEO_IN_DMA(channel));
134
	/* Re-enable error interrupts every time a channel is initialized */
135
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(5));
136
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(6));
137
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(9));
138
	ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(10));
139

140
	ipu->dc_di_assignment[5] = 0;
141

142
	_ipu_dc_init(ipu, 5, 0, 0, IPU_PIX_FMT_RGB666);
143

144
	return 0;
145
}
146

147
void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel) {
148
	uint32_t ipu_conf;
149

150
	_ipu_dc_uninit(ipu, 5);
151

152
	ipu_conf = ipu_cm_read(ipu, IPU_CONF);
153
	ipu_conf &= ~IPU_CONF_DC_EN;
154
	ipu_conf &= ~IPU_CONF_DP_EN;
155
	ipu_conf &= ~IPU_CONF_DMFC_EN;
156
	ipu_conf &= ~IPU_CONF_DI0_EN;
157
	ipu_cm_write(ipu, ipu_conf, IPU_CONF);
158
}
159

160
int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
161
				ipu_buffer_t type,
162
				uint32_t pixel_fmt,
163
				uint16_t width, uint16_t height,
164
				uint32_t stride,
165
				dma_addr_t phyaddr_0) {
166
	uint32_t dma_chan = IPU_CHAN_VIDEO_IN_DMA(channel);
167

168
	assert(dma_chan == 23); /* XXX */
169

170
	_ipu_ch_param_init(ipu, dma_chan, pixel_fmt, width, height, stride, 0, 0, 0,
171
			   phyaddr_0);
172

173
	return 0;
174
}
175

176
int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel) {
177
	uint32_t reg;
178
	uint32_t ipu_conf;
179
	uint32_t in_dma = IPU_CHAN_VIDEO_IN_DMA(channel);
180

181
	assert(in_dma == 23); /* XXX */
182

183
	ipu_conf = IPU_CONF_DP_EN | IPU_CONF_DC_EN | IPU_CONF_DMFC_EN;
184
	ipu_conf |= IPU_CONF_DI0_EN;
185
	ipu_cm_write(ipu, ipu_conf, IPU_CONF);
186

187
	reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(in_dma));
188
	ipu_idmac_write(ipu, reg | idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
189
	reg = ipu_idmac_read(ipu, IDMAC_WM_EN(in_dma));
190
	ipu_idmac_write(ipu, reg | idma_mask(in_dma), IDMAC_WM_EN(in_dma));
191

192
	_ipu_dp_dc_enable(ipu, channel);
193

194
	ipu_cm_write(ipu, 0x1400000, IPU_DISP_GEN);
195

196
	return 0;
197
}
198

199
void _ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
200
		uint32_t bufNum) {
201
	uint32_t dma_ch = IPU_CHAN_VIDEO_IN_DMA(channel);
202

203
	assert(dma_ch == 23); /* XXX */
204

205
	ipu_cm_write(ipu, 0xF0300000, IPU_GPR); /* write one to clear */
206
	ipu_cm_write(ipu, idma_mask(dma_ch), IPU_CHA_BUF0_RDY(dma_ch));
207
	ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
208
}
209

210
void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
211
		uint32_t bufNum) {
212
	_ipu_clear_buffer_ready(ipu, channel, type, bufNum);
213
}
214

215
int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop) {
216
	uint32_t reg;
217
	uint32_t in_dma = IPU_CHAN_VIDEO_IN_DMA(channel);
218

219
	assert(in_dma == 23); /* XXX */
220

221
	reg = ipu_idmac_read(ipu, IDMAC_WM_EN(in_dma));
222
	ipu_idmac_write(ipu, reg & ~idma_mask(in_dma), IDMAC_WM_EN(in_dma));
223

224
	reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(in_dma));
225
	ipu_idmac_write(ipu, reg & ~idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
226
	ipu_cm_write(ipu, idma_mask(in_dma), IPU_CHA_CUR_BUF(in_dma));
227

228
	_ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 0);
229

230
	return 0;
231
}
232

233
void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq) {
234
	uint32_t reg;
235

236
	reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
237
	reg &= ~IPUIRQ_2_MASK(irq);
238
	ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
239
}
240

241
void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq) {
242
	ipu_cm_write(ipu, IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
243
}
244

245
int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
246
		    /* irq_return_t(*handler) (int, void *), */
247
		    uint32_t irq_flags, const char *devname, void *dev_id) {
248
	uint32_t reg;
249

250
	ipu_cm_write(ipu, IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
251
	reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
252
	reg |= IPUIRQ_2_MASK(irq);
253
	ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
254

255
	return 0;
256
}
257

258
void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id) {
259
	uint32_t reg;
260

261
	reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
262
	reg &= ~IPUIRQ_2_MASK(irq);
263
	ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
264
}
265

266
PERIPH_MEMORY_DEFINE(ipu, IPU_BASE, 0x200000);
267

268
#define DCIC1_BASE 0x20E4000
269
#define DCIC2_BASE 0x20E8000
270

271
PERIPH_MEMORY_DEFINE(ipu_dcic1, DCIC1_BASE, 0x20);
272

273
PERIPH_MEMORY_DEFINE(ipu_dcic2, DCIC2_BASE, 0x20);
274

275
PERIPH_MEMORY_DEFINE(ipu_src, SRC_BASE, 0x4);
276

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.