summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/imx/hdp/imx-hdp.h
blob: 41ea3b963aa85efb902f424d556ab40f313255a8 (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
/*
 * Copyright 2017-2018 NXP
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */
#ifndef _IMX_HDP_H_
#define _IMX_HDP_H_

#include <linux/regmap.h>
#include <linux/mutex.h>
#include <drm/drm_of.h>
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder_slave.h>
#include <drm/drm_atomic.h>
#include <soc/imx8/sc/sci.h>

#include <drm/drm_dp_helper.h>
#include "../../../../mxc/hdp/all.h"
#include "../../../../mxc/hdp-cec/imx-hdp-cec.h"

#define HDP_DUAL_MODE_MIN_PCLK_RATE	300000	/* KHz */
#define HDP_SINGLE_MODE_MAX_WIDTH	1920

/* For testing hdp firmware define DEBUG_FW_LOAD */
#undef DEBUG_FW_LOAD
#define PLL_1188MHZ (1188000000)
#define PLL_675MHZ (675000000)

#define HDP_TX_SS_LIS_BASE   0x0000
#define HDP_TX_SS_CSR_BASE   0x1000
#define HDP_TX_SS_GPIO_BASE  0x2000
#define HDP_TX_SS_CTRL0_BASE 0x8000

#define CSR_PIXEL_LINK_MUX_CTL		0x00
#define PL_MUX_CTL_VCP_OFFSET		5
#define PL_MUX_CTL_HCP_OFFSET		4
#define PL_MUX_CTL_PL_MUX_OFFSET	2
#define PL_MUX_CTL_PL_SEL_OFFSET	0

#define CSR_PIXEL_LINK_MUX_STATUS	0x04
#define PL_MUX_STATUS_PL1_INT_OFFSET 18
#define PL_MUX_STATUS_PL1_ADD_OFFSET 16
#define PL_MUX_STATUS_PL1_TYP_OFFSET 11
#define PL_MUX_STATUS_PL0_INT_OFFSET 9
#define PL_MUX_STATUS_PL0_ADD_OFFSET 7
#define PL_MUX_STATUS_PL0_TYP_OFFSET 2
#define PL_MUX_STATUS_PL_DLY_OFFSET 0

#define CSR_HDP_TX_CTRL_CTRL0		0x08
#define CSR_HDP_TX_CTRL_CTRL1		0x0c

#define HOTPLUG_DEBOUNCE_MS		200

#define VIC_MODE_97_60Hz 97
#define VIC_MODE_96_50Hz 96
#define VIC_MODE_95_30Hz 95
#define VIC_MODE_94_25Hz 94
#define VIC_MODE_93_24Hz 93

/**
 * imx_hdp_call - Calls a struct imx hdp_operations operation on
 *	an entity
 *
 * @entity: entity where the @operation will be called
 * @operation: type of the operation. Should be the name of a member of
 *	struct &media_entity_operations.
 *
 * This helper function will check if @operation is not %NULL. On such case,
 * it will issue a call to @operation\(@args\).
 */

#define imx_hdp_call(hdp, operation, args...)			\
	(!(hdp) ? -ENODEV : (((hdp)->ops && (hdp)->ops->operation) ?	\
	 (hdp)->ops->operation(args) : ENOIOCTLCMD))

#define clks_to_imx_hdp(env) \
	container_of(env, struct imx_hdp, clks)

#define state_to_imx_hdp(env) \
	container_of(env, struct imx_hdp, state)

struct hdp_clks;

struct hdp_ops {
	void (*fw_load)(state_struct *state);
	int (*fw_init)(state_struct *state);
	int (*phy_init)(state_struct *state, struct drm_display_mode *mode,
			int format, int color_depth);
	void (*mode_set)(state_struct *state, struct drm_display_mode *mode,
			 int format, int color_depth, int max_link);
	bool (*mode_fixup)(state_struct *state,
			   const struct drm_display_mode *mode,
			   struct drm_display_mode *adjusted_mode);
	int (*get_edid_block)(void *data, u8 *buf, u32 block, size_t len);
	int (*get_hpd_state)(state_struct *state, u8 *hpd);
	int (*write_hdr_metadata)(state_struct *state,
				  union hdmi_infoframe *hdr_infoframe);

	void (*phy_reset)(sc_ipc_t ipcHndl, struct hdp_mem *mem, u8 reset);
	int (*pixel_link_validate)(state_struct *state);
	int (*pixel_link_invalidate)(state_struct *state);
	int (*pixel_link_sync_ctrl_enable)(state_struct *state);
	int (*pixel_link_sync_ctrl_disable)(state_struct *state);
	void (*pixel_link_mux)(state_struct *state,
			       struct drm_display_mode *mode);
	void (*pixel_engine_reset)(state_struct *state);

	int (*clock_init)(struct hdp_clks *clks);
	int (*ipg_clock_enable)(struct hdp_clks *clks);
	void (*ipg_clock_disable)(struct hdp_clks *clks);
	void (*ipg_clock_set_rate)(struct hdp_clks *clks);
	int (*pixel_clock_enable)(struct hdp_clks *clks);
	void (*pixel_clock_disable)(struct hdp_clks *clks);
	void (*pixel_clock_set_rate)(struct hdp_clks *clks);
	int (*pixel_clock_range)(struct drm_display_mode *mode);
};

struct hdp_devtype {
	u8 is_hdmi_level;
	u8 audio_type;
	struct hdp_ops *ops;
	struct hdp_rw_func *rw;
	u32 connector_type;
};

struct hdp_video {
	u32 bpp;
	u32 format;
	u32 lanes;
	u32 color_type; /* bt */
	u32 color_depth;  /* bpc */
	struct drm_display_mode cur_mode;
	struct drm_display_mode pre_mode;
	void __iomem *regs_base;
};

struct hdp_audio {
	u32 interface;  /* I2S SPDIF  */
	u32 freq;
	u32 nlanes;
	u32 nChannels;
	u32 sample_width;
	u32 sample_rate;
	u32 audio_cts;
	u32 audio_n;
	bool audio_enable;
	spinlock_t audio_lock;
	struct mutex audio_mutex;
	void __iomem *regs_base;
};

struct hdp_hdcp {
	void __iomem *regs_base;
};

struct hdp_phy {
	u32 index;
	u32 number;
	bool enabled;
	struct phy *phy;
	void __iomem *regs_base;
};

struct hdp_clks {
	struct clk *av_pll;
	struct clk *dig_pll;
	struct clk *clk_ipg;
	struct clk *clk_core;
	struct clk *clk_pxl;
	struct clk *clk_pxl_mux;
	struct clk *clk_pxl_link;

	struct clk *clk_hdp;
	struct clk *clk_phy;
	struct clk *clk_apb;

	struct clk *clk_lis;
	struct clk *clk_msi;
	struct clk *clk_lpcg;
	struct clk *clk_even;
	struct clk *clk_dbl;
	struct clk *clk_vif;
	struct clk *clk_apb_csr;
	struct clk *clk_apb_ctrl;
	struct clk *av_pll_div;
	struct clk *dig_pll_div;
	struct clk *clk_i2s;
	struct clk *clk_i2s_bypass;
};

enum hdp_tx_irq {
	HPD_IRQ_IN,
	HPD_IRQ_OUT,
	HPD_IRQ_NUM,
};

struct imx_hdp {
	struct device *dev;
	struct drm_connector connector;
	struct drm_encoder encoder;
	struct drm_bridge bridge;

	struct edid *edid;
	char cable_state;
	int hdmi_ctrl_gpio;

	struct hdp_mem mem;

	u8 is_cec;
	u8 is_edp;
	u8 is_dp;
	u8 is_digpll_dp_pclock;
	u8 no_edid;
	u8 audio_type;
	u32 dp_lane_mapping;
	u32 dp_link_rate;
	u32 dp_num_lanes;

	struct mutex mutex;		/* for state below and previous_mode */
	enum drm_connector_force force;	/* mutex-protected force state */

	struct hdp_video video;

	struct drm_dp_aux aux;
	struct mutex aux_mutex;

	struct drm_dp_link dp_link;
	S_LINK_STAT lkstat;
	ENUM_AFE_LINK_RATE link_rate;

	sc_ipc_t ipcHndl;
	u32 mu_id;
	u32 dual_mode;
	struct hdp_ops *ops;
	struct hdp_rw_func *rw;
	struct hdp_clks clks;
	state_struct state;
	int vic;
	int irq[HPD_IRQ_NUM];
	struct delayed_work hotplug_work;

	struct imx_cec_dev cec;

	int bpc;
	VIC_PXL_ENCODING_FORMAT format;
	bool hdr_metadata_present;
	bool hdr_mode;
};

void imx_hdp_register_audio_driver(struct device *dev);
void imx_arc_power_up(state_struct *state);
void imx_arc_calibrate(state_struct *state);
void imx_arc_config(state_struct *state);

#endif