summaryrefslogtreecommitdiff
path: root/drivers/video/imx/ipu.h
blob: ae40e20bc2879ee9f1d545b5a9e061e3f99773dc (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Code fixes:
 *
 * (C) Copyright 2025
 * Brian Ruley, GE HealthCare, [email protected]
 *
 * Porting to u-boot:
 *
 * (C) Copyright 2010
 * Stefano Babic, DENX Software Engineering, [email protected]
 *
 * Linux IPU driver for MX51:
 *
 * (C) Copyright 2005-2010 Freescale Semiconductor, Inc.
 */

#ifndef __ASM_ARCH_IPU_H__
#define __ASM_ARCH_IPU_H__

#if !CONFIG_IS_ENABLED(IPU_CLK_LEGACY)
#include <clk.h>
#endif
#include <ipu_pixfmt.h>
#include <linux/types.h>

#define IPUV3_CLK_MX51 133000000
#define IPUV3_CLK_MX53 200000000
#define IPUV3_CLK_MX6Q 264000000
#define IPUV3_CLK_MX6DL 198000000

#define IDMA_CHAN_INVALID 0xFF
#define HIGH_RESOLUTION_WIDTH 1024

struct ipu_ctx;

#if CONFIG_IS_ENABLED(IPU_CLK_LEGACY)

struct clk {
	const char *name;
	int id;
	/* The IPU context of this clock */
	struct ipu_ctx *ctx;
	/* Source clock this clk depends on */
	struct clk *parent;
	/* Secondary clock to enable/disable with this clock */
	struct clk *secondary;
	/* Current clock rate */
	unsigned long rate;
	/* Reference count of clock enable/disable */
	__s8 usecount;
	/* Register bit position for clock's enable/disable control. */
	u8 enable_shift;
	/* Register address for clock's enable/disable control. */
	void *enable_reg;
	u32 flags;
	/*
	 * Function ptr to recalculate the clock's rate based on parent
	 * clock's rate
	 */
	void (*recalc)(struct clk *clk);
	/*
	 * Function ptr to set the clock to a new rate. The rate must match a
	 * supported rate returned from round_rate. Leave blank if clock is not
	* programmable
	 */
	int (*set_rate)(struct clk *clk, unsigned long rate);
	/*
	 * Function ptr to round the requested clock rate to the nearest
	 * supported rate that is less than or equal to the requested rate.
	 */
	unsigned long (*round_rate)(struct clk *clk, unsigned long rate);
	/*
	 * Function ptr to enable the clock. Leave blank if clock can not
	 * be gated.
	 */
	int (*enable)(struct clk *clk);
	/*
	 * Function ptr to disable the clock. Leave blank if clock can not
	 * be gated.
	 */
	void (*disable)(struct clk *clk);
	/* Function ptr to set the parent clock of the clock. */
	int (*set_parent)(struct clk *clk, struct clk *parent);
};

/* Legacy clock API functions */
void clk_enable(struct clk *clk);
void clk_disable(struct clk *clk);
int clk_get_usecount(struct clk *clk);
u32 clk_get_rate(struct clk *clk);
struct clk *clk_get_parent(struct clk *clk);
int clk_set_rate(struct clk *clk, unsigned long rate);
long clk_round_rate(struct clk *clk, unsigned long rate);
int clk_set_parent(struct clk *clk, struct clk *parent);

/* IPU clock initialization */
int ipu_clk_init_legacy(struct ipu_ctx *ctx);
int ipu_ldb_clk_init_legacy(struct ipu_ctx *ctx);
int ipu_pixel_clk_init_legacy(struct ipu_ctx *ctx, int id);

#else

static inline int clk_get_usecount(struct clk *clk)
{
        return clk->enable_count;
}

/* Stub functions for non-legacy builds */
static inline int ipu_clk_init_legacy(struct ipu_ctx *ctx)
{
	return -ENOSYS;
}

static inline int ipu_ldb_clk_init_legacy(struct ipu_ctx *ctx)
{
	return -ENOSYS;
}

static inline int ipu_pixel_clk_init_legacy(struct ipu_ctx *ctx, int id)
{
	return -ENOSYS;
}

#endif /* CONFIG_IS_ENABLED(IPU_CLK_LEGACY) */

struct udevice;

/*
 * Per-IPU context used by ipu_common to manage clocks and channel state.
 * Lifetime is owned by the IPU DM driver
 */
struct ipu_ctx {
	struct udevice *dev;
	int dev_id;

	struct clk *ipu_clk;
	struct clk *ldb_clk;
	unsigned char ipu_clk_enabled;
	struct clk *di_clk[2];
	struct clk *pixel_clk[2];

	u8 dc_di_assignment[10];
	u32 channel_init_mask;
	u32 channel_enable_mask;

	int ipu_dc_use_count;
	int ipu_dp_use_count;
	int ipu_dmfc_use_count;
	int ipu_di_use_count[2];
};

/**
 * @disp:	    The DI the panel is attached to.
 * @pixel_clk_rate: Desired pixel clock frequency in Hz.
 * @pixel_fmt:	    Input parameter for pixel format of buffer.
 *		    Pixel format is a FOURCC ASCII code.
 * @width:	    The width of panel in pixels.
 * @height:	    The height of panel in pixels.
 * @h_start_width:  The number of pixel clocks between the HSYNC
 *		    signal pulse and the start of valid data.
 * @h_sync_width:   The width of the HSYNC signal in units of pixel
 *		    clocks.
 * @h_end_width:    The number of pixel clocks between the end of
 *		    valid data and the HSYNC signal for next line.
 * @v_start_width:  The number of lines between the VSYNC
 *		    signal pulse and the start of valid data.
 * @v_sync_width:   The width of the VSYNC signal in units of lines
 * @v_end_width:    The number of lines between the end of valid
 *		    data and the VSYNC signal for next frame.
 * @ctx:	    The IPU context of the display.
 */
struct ipu_di_config {
	int disp;
	u32 pixel_clk_rate;
	u32 pixel_fmt;
	u16 width;
	u16 height;
	u16 h_start_width;
	u16 h_sync_width;
	u16 h_end_width;
	u16 v_start_width;
	u16 v_sync_width;
	u16 v_end_width;
	u32 v_to_h_sync;

	struct ipu_ctx *ctx;
};

/*
 * Enumeration of Synchronous (Memory-less) panel types
 */
typedef enum {
	IPU_PANEL_SHARP_TFT,
	IPU_PANEL_TFT,
} ipu_panel_t;

/*
 * IPU Driver channels definitions.
 * Note these are different from IDMA channels
 */
#define IPU_MAX_CH 32
#define _MAKE_CHAN(num, v_in, g_in, a_in, out) \
	((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out)
#define _MAKE_ALT_CHAN(ch) (ch | (IPU_MAX_CH << 24))
#define IPU_CHAN_ID(ch) (ch >> 24)
#define IPU_CHAN_ALT(ch) (ch & 0x02000000)
#define IPU_CHAN_ALPHA_IN_DMA(ch) ((u32)(ch >> 6) & 0x3F)
#define IPU_CHAN_GRAPH_IN_DMA(ch) ((u32)(ch >> 12) & 0x3F)
#define IPU_CHAN_VIDEO_IN_DMA(ch) ((u32)(ch >> 18) & 0x3F)
#define IPU_CHAN_OUT_DMA(ch) ((u32)(ch & 0x3F))
#define NO_DMA 0x3F
#define ALT 1

/*
 * Enumeration of IPU logical channels. An IPU logical channel is defined as a
 * combination of an input (memory to IPU), output (IPU to memory), and/or
 * secondary input IDMA channels and in some cases an Image Converter task.
 * Some channels consist of only an input or output.
 */
typedef enum {
	CHAN_NONE = -1,

	MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA),
	MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA),
	MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA),
	MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA),

	MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA),
	MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA),
	MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0),
	MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0),

	DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
	DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA),

} ipu_channel_t;

/*
 * Enumeration of types of buffers for a logical channel.
 */
typedef enum {
	IPU_OUTPUT_BUFFER = 0, /*< Buffer for output from IPU */
	IPU_ALPHA_IN_BUFFER = 1, /*< Buffer for input to IPU */
	IPU_GRAPH_IN_BUFFER = 2, /*< Buffer for input to IPU */
	IPU_VIDEO_IN_BUFFER = 3, /*< Buffer for input to IPU */
	IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER,
	IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER,
} ipu_buffer_t;

#define IPU_PANEL_SERIAL 1
#define IPU_PANEL_PARALLEL 2

struct ipu_channel {
	u8 video_in_dma;
	u8 alpha_in_dma;
	u8 graph_in_dma;
	u8 out_dma;
};

enum ipu_dmfc_type {
	DMFC_NORMAL = 0,
	DMFC_HIGH_RESOLUTION_DC,
	DMFC_HIGH_RESOLUTION_DP,
	DMFC_HIGH_RESOLUTION_ONLY_DP,
};

/*
 * Union of initialization parameters for a logical channel.
 */
typedef union {
	struct {
		u32 di;
		unsigned char interlaced;
	} mem_dc_sync;
	struct {
		u32 temp;
	} mem_sdc_fg;
	struct {
		u32 di;
		unsigned char interlaced;
		u32 in_pixel_fmt;
		u32 out_pixel_fmt;
		unsigned char alpha_chan_en;
	} mem_dp_bg_sync;
	struct {
		u32 temp;
	} mem_sdc_bg;
	struct {
		u32 di;
		unsigned char interlaced;
		u32 in_pixel_fmt;
		u32 out_pixel_fmt;
		unsigned char alpha_chan_en;
	} mem_dp_fg_sync;
} ipu_channel_params_t;

/*
 * Enumeration of IPU interrupts.
 */
enum ipu_irq_line {
	IPU_IRQ_DP_SF_END = 448 + 3,
	IPU_IRQ_DC_FC_1 = 448 + 9,
};

/*
 * Bitfield of Display Interface signal polarities.
 */
typedef struct {
	unsigned datamask_en : 1;
	unsigned ext_clk : 1;
	unsigned interlaced : 1;
	unsigned odd_field_first : 1;
	unsigned clksel_en : 1;
	unsigned clkidle_en : 1;
	unsigned data_pol : 1; /* true = inverted */
	unsigned clk_pol : 1; /* true = rising edge */
	unsigned enable_pol : 1;
	unsigned hsync_pol : 1; /* true = active high */
	unsigned vsync_pol : 1;
} ipu_di_signal_cfg_t;

typedef enum { RGB, YCBCR, YUV } ipu_color_space_t;

/* Common IPU API */
int32_t ipu_init_channel(struct ipu_ctx *ctx, ipu_channel_t channel,
			 ipu_channel_params_t *params);
void ipu_uninit_channel(struct ipu_ctx *ctx, ipu_channel_t channel);

int32_t ipu_init_channel_buffer(ipu_channel_t channel, ipu_buffer_t type,
				u32 pixel_fmt, u16 width, u16 height,
				u32 stride, dma_addr_t phyaddr_0,
				dma_addr_t phyaddr_1, u32 u_offset,
				u32 v_offset);

void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type,
			    u32 buf_num);
int32_t ipu_enable_channel(struct ipu_ctx *ctx, ipu_channel_t channel);
int32_t ipu_disable_channel(struct ipu_ctx *ctx, ipu_channel_t channel);

int32_t ipu_init_sync_panel(struct ipu_di_config *di, ipu_di_signal_cfg_t sig);

int32_t ipu_disp_set_global_alpha(ipu_channel_t channel, unsigned char enable,
				  u8 alpha);
int32_t ipu_disp_set_color_key(ipu_channel_t channel, unsigned char enable,
			       u32 color_key);

u32 bytes_per_pixel(u32 fmt);

void ipu_dump_registers(void);
struct ipu_ctx *ipu_probe(struct udevice *dev);
bool ipu_clk_enabled(struct ipu_ctx *ctx);

void ipu_dmfc_init(int dmfc_type, int first);
void ipu_init_dc_mappings(void);
void ipu_dmfc_set_wait4eot(int dma_chan, int width);
void ipu_dc_init(int dc_chan, int di, unsigned char interlaced);
void ipu_dc_uninit(int dc_chan);
void ipu_dp_dc_enable(struct ipu_ctx *ctx, ipu_channel_t channel);
int ipu_dp_init(ipu_channel_t channel, u32 in_pixel_fmt, u32 out_pixel_fmt);
void ipu_dp_uninit(ipu_channel_t channel);
void ipu_dp_dc_disable(struct ipu_ctx *ctx, ipu_channel_t channel,
		       unsigned char swap);
ipu_color_space_t format_to_colorspace(u32 fmt);
#endif