summaryrefslogtreecommitdiff
path: root/include/video/display.h
blob: 11d7032b7a61228dce7c6e7cdba095ba186b8911 (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
/*
 * Display Core
 *
 * Copyright (C) 2012 Renesas Solutions Corp.
 *
 * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef __DISPLAY_H__
#define __DISPLAY_H__

#include <linux/kref.h>
#include <linux/list.h>
#include <linux/module.h>
#include <video/omapdss.h>

struct display_entity;
struct video_source;
struct videomode;

/* -----------------------------------------------------------------------------
 * Display Entity
 */

/* Hack to get the first registered display entity */
struct display_entity *display_entity_get_first(void);

enum display_entity_state {
	DISPLAY_ENTITY_STATE_OFF,
	DISPLAY_ENTITY_STATE_STANDBY,
	DISPLAY_ENTITY_STATE_ON,
};

enum display_entity_interface_type {
	DISPLAY_ENTITY_INTERFACE_DPI,
	DISPLAY_ENTITY_INTERFACE_DSI,
};

#define DSI_MODE_VIDEO			(1 << 0)
#define DSI_MODE_VIDEO_BURST		(1 << 1)
#define DSI_MODE_VIDEO_SYNC_PULSE	(1 << 2)
#define DSI_MODE_VIDEO_AUTO_VERT	(1 << 3)
#define DSI_MODE_VIDEO_HSE		(1 << 4)
#define DSI_MODE_VIDEO_HFP		(1 << 5)
#define DSI_MODE_VIDEO_HBP		(1 << 6)
#define DSI_MODE_VIDEO_HSA		(1 << 7)
#define DSI_MODE_VSYNC_FLUSH		(1 << 8)
#define DSI_MODE_EOT_PACKET		(1 << 9)

enum mipi_dsi_pixel_format {
	DSI_FMT_RGB888,
	DSI_FMT_RGB666,
	DSI_FMT_RGB666_PACKED,
	DSI_FMT_RGB565,
};

struct mipi_dsi_interface_params {
	enum mipi_dsi_pixel_format format;
	unsigned long mode;
	unsigned long hs_clk_freq;
	unsigned long esc_clk_freq;
	unsigned char data_lanes;
	unsigned char cmd_allow;
};

struct display_entity_interface_params {
	enum display_entity_interface_type type;
	union {
		struct mipi_dsi_interface_params dsi;
	} p;
};

struct display_entity_control_ops {
	int (*set_state)(struct display_entity *ent,
			 enum display_entity_state state);
	int (*update)(struct display_entity *ent,
			void (*callback)(int, void *), void *data);
	int (*get_modes)(struct display_entity *ent,
			 const struct videomode **modes);
	int (*get_params)(struct display_entity *ent,
			  struct display_entity_interface_params *params);
	int (*get_size)(struct display_entity *ent,
			unsigned int *width, unsigned int *height);
};

struct display_entity {
	struct list_head list;
	struct device *dev;
	struct device_node *of_node;
	struct module *owner;
	struct kref ref;

	const char *src_name;
	int src_id;
	struct video_source *source;

	const struct display_entity_control_ops *ops;

	void(*release)(struct display_entity *ent);

	enum display_entity_state state;
};

int display_entity_set_state(struct display_entity *entity,
			     enum display_entity_state state);
int display_entity_get_params(struct display_entity *entity,
			      struct display_entity_interface_params *params);
int display_entity_get_modes(struct display_entity *entity,
			     const struct videomode **modes);
int display_entity_get_size(struct display_entity *entity,
			    unsigned int *width, unsigned int *height);

struct display_entity *display_entity_get(struct display_entity *entity);
void display_entity_put(struct display_entity *entity);

int __must_check __display_entity_register(struct display_entity *entity,
					   struct module *owner);
void display_entity_unregister(struct display_entity *entity);

#define display_entity_register(display_entity) \
	__display_entity_register(display_entity, THIS_MODULE)


/* -----------------------------------------------------------------------------
 * Video Source
 */

enum video_source_stream_state {
	DISPLAY_ENTITY_STREAM_STOPPED,
	DISPLAY_ENTITY_STREAM_CONTINUOUS,
};

struct common_video_source_ops {
	int (*set_stream)(struct video_source *src,
			 enum video_source_stream_state state);
	int (*bind)(struct video_source *src, struct display_entity *sink);
	int (*unbind)(struct video_source *src, struct display_entity *sink);
};

struct dpi_video_source_ops {
	int (*set_videomode)(struct video_source *src,
			const struct videomode *vm);
	int (*set_data_lines)(struct video_source *src, int lines);
};

struct dsi_video_source_ops {
	/* enable/disable dsi bus */
	int (*enable)(struct video_source *src);
	int (*disable)(struct video_source *src);

	/* bus configuration */
	int (*configure_pins)(struct video_source *src,
			const struct omap_dsi_pin_config *pins);
	int (*set_clocks)(struct video_source *src,
			unsigned long ddr_clk,
			unsigned long lp_clk);
	/* NOTE: Do we really need configure_pins and set_clocks here? */

	void (*enable_hs)(struct video_source *src, bool enable);

	/* data transfer */
	int (*dcs_write)(struct video_source *src, int channel,
			const u8 *data, size_t len);
	int (*dcs_read)(struct video_source *src, int channel, u8 dcs_cmd,
			u8 *data, size_t len);
	/* NOTE: Do we need more write and read types? */

	int (*update)(struct video_source *src, int channel,
			void (*callback)(int, void *), void *data);
};

struct dvi_video_source_ops {
	int (*set_videomode)(struct video_source *src,
			const struct videomode *vm);
};

struct video_source {
	struct list_head list;
	struct device *dev;
	struct device_node *of_node;
	struct module *owner;
	struct kref ref;

	struct display_entity *sink;

	const char *name;
	int id;

	const struct common_video_source_ops *common_ops;

	union {
		const struct dpi_video_source_ops *dpi;
		const struct dsi_video_source_ops *dsi;
		const struct dvi_video_source_ops *dvi;
	} ops;

	void(*release)(struct video_source *src);
};

static inline int dsi_dcs_write(struct video_source *src, int channel,
						const u8 *data, size_t len)
{
	if (!src->ops.dsi || !src->ops.dsi->dcs_write)
		return -EINVAL;

	return src->ops.dsi->dcs_write(src, channel, data, len);
}

static inline int dsi_dcs_read(struct video_source *src, int channel,
					u8 dcs_cmd, u8 *data, size_t len)
{
	if (!src->ops.dsi || !src->ops.dsi->dcs_read)
		return -EINVAL;

	return src->ops.dsi->dcs_read(src, channel, dcs_cmd, data, len);
}


#define video_source_register(video_source) \
	__video_source_register(video_source, THIS_MODULE)

int __must_check __video_source_register(struct video_source *entity,
							struct module *owner);
void video_source_unregister(struct video_source *entity);

#endif /* __DISPLAY_H__ */