1 #ifndef __LOONGSON_DRV_H__
2 #define __LOONGSON_DRV_H__
3 
4 #include <linux/i2c.h>
5 #include <linux/i2c-algo-bit.h>
6 #include <linux/module.h>
7 #include <linux/types.h>
8 
9 #include <drm/drm_drv.h>
10 #include <drm/drm_encoder.h>
11 #include <drm/drm_fb_helper.h>
12 #include <drm/drm_gem.h>
13 #include <drm/drm_irq.h>
14 #include <drm/drm_vblank.h>
15 
16 #include <loongson.h>
17 #include "loongson_i2c.h"
18 #include "loongson_vbios.h"
19 
20 #define to_loongson_crtc(x) container_of(x, struct loongson_crtc, base)
21 #define to_loongson_encoder(x) container_of(x, struct loongson_encoder, base)
22 #define to_loongson_connector(x) container_of(x, struct loongson_connector, base)
23 
24 #define LOONGSON_MAX_FB_HEIGHT	4096
25 #define LOONGSON_MAX_FB_WIDTH	4096
26 
27 #define CUR_WIDTH_SIZE		32
28 #define CUR_HEIGHT_SIZE		32
29 
30 #define LO_OFF	0
31 #define HI_OFF	8
32 
33 #define LS7A_PIX0_PLL		(void *)TO_UNCACHE(LS7A_CHIPCFG_REG_BASE + 0x04b0)
34 #define LS7A_PIX1_PLL		(void *)TO_UNCACHE(LS7A_CHIPCFG_REG_BASE + 0x04c0)
35 
36 #define CURIOSET_CORLOR		0x4607
37 #define CURIOSET_POSITION	0x4608
38 #define CURIOLOAD_ARGB		0x4609
39 #define CURIOLOAD_IMAGE		0x460A
40 #define CURIOHIDE_SHOW		0x460B
41 #define FBEDID_GET		0X860C
42 
43 #define CRTC_REG_OFFSET		0x10
44 
45 #define CFG_FMT			GENMASK(2,0)
46 #define CFG_FBSWITCH		BIT(7)
47 #define CFG_ENABLE		BIT(8)
48 #define CFG_PANELSWITCH 	BIT(9)
49 #define CFG_FBNUM_BIT		11
50 #define CFG_FBNUM		BIT(11)
51 #define CFG_GAMMAR		BIT(12)
52 #define CFG_RESET		BIT(20)
53 
54 #define FB_CFG_DVO_REG		(0x1240)
55 #define FB_ADDR0_DVO_REG	(0x1260)
56 #define FB_ADDR1_DVO_REG	(0x1580)
57 #define FB_STRI_DVO_REG		(0x1280)
58 #define FB_DITCFG_DVO_REG	(0x1360)
59 #define FB_DITTAB_LO_DVO_REG	(0x1380)
60 #define FB_DITTAB_HI_DVO_REG	(0x13a0)
61 #define FB_PANCFG_DVO_REG	(0x13c0)
62 #define FB_PANTIM_DVO_REG	(0x13e0)
63 #define FB_HDISPLAY_DVO_REG	(0x1400)
64 #define FB_HSYNC_DVO_REG	(0x1420)
65 #define FB_VDISPLAY_DVO_REG	(0x1480)
66 #define FB_VSYNC_DVO_REG	(0x14a0)
67 #define FB_GAMINDEX_DVO_REG	(0x14e0)
68 #define FB_GAMDATA_DVO_REG	(0x1500)
69 
70 #define HDMI_ZONEIDLE_REG 	(0x1700)
71 #define HDMI_CTRL_REG		(0x1720)
72 
73 #define HDMI_AUDIO_BUF_REG	(0x1740)
74 #define HDMI_AUDIO_NCFG_REG	(0x1760)
75 #define HDMI_AUDIO_CTSCFG_REG	(0x1780)
76 #define HDMI_AUDIO_CTSCALCFG_REG	(0x17a0)
77 #define HDMI_AUDIO_INFOFRAME_REG	(0x17c0)
78 #define HDMI_AUDIO_SAMPLE_REG	(0x17e0)
79 
80 #define HDMI_PHY_CTRL_REG	(0x1800)
81 #define HDMI_PHY_PLLCFG_REG	(0x1820)
82 
83 #define FB_CUR_CFG_REG		(0x1520)
84 #define FB_CUR_ADDR_REG		(0x1530)
85 #define FB_CUR_LOC_ADDR_REG	(0x1540)
86 #define FB_CUR_BACK_REG		(0x1550)
87 #define FB_CUR_FORE_REG		(0x1560)
88 #define FB_INT_REG		(0x1570)
89 
90 #define INT_DVO1_VSYNC		0
91 #define INT_DVO1_HSYNC		1
92 #define INT_DVO0_VSYNC		2
93 #define INT_DVO0_HSYNC		3
94 #define INT_CURSOR_FB_END	4
95 #define INT_DVO1_FB_END		5
96 #define INT_DVO0_FB_END		6
97 
98 #define MAX_CRTC 2
99 
100 enum loongson_chip {
101 	dc_7a1000,
102 	dc_7a2000
103 };
104 
105 struct pix_pll {
106 	unsigned int l2_div;
107 	unsigned int l1_loopc;
108 	unsigned int l1_frefc;
109 };
110 
111 struct config_reg {
112 	u8 dev_addr;
113 	u8 reg;
114 	u8 value;
115 } __packed;
116 
117 struct cfg_encoder {
118 	u8 reg_num;
119 	u32 hdisplay;
120 	u32 vdisplay;
121 	struct config_reg config_regs[256];
122 };
123 
124 struct loongson_crtc {
125 	struct drm_crtc base;
126 	unsigned int crtc_id;
127 	uint32_t cfg_reg;
128 	struct drm_plane *primary; /* Primary panel belongs to this crtc */
129 	struct drm_pending_vblank_event *event;
130 	struct loongson_drm_device *ldev;
131 };
132 
133 struct loongson_encoder {
134 	struct drm_encoder base;
135 	u32 type;
136 	u32 i2c_id;
137 	int encoder_id;
138 	struct loongson_i2c *i2c;
139 	struct loongson_crtc *lcrtc; /* Binding crtc, not actual one */
140 };
141 
142 struct loongson_connector {
143 	struct drm_connector base;
144 	u16 id;
145 	u32 type;
146 	u16 i2c_id;
147 	u16 hotplug;
148 	u16 edid_method;
149 	u8 *vbios_edid;
150 	struct loongson_i2c *i2c;
151 	struct loongson_drm_device *ldev;
152 };
153 
154 struct loongson_mode_info {
155 	bool mode_config_initialized;
156 	struct loongson_crtc *crtc;
157 	struct loongson_encoder *encoder;
158 	struct loongson_connector *connector;
159 };
160 
161 struct loongson_drm_device {
162 	struct drm_device *dev;
163 	struct drm_atomic_state	*state;
164 	struct pci_dev *gpu_pdev; /* LS7A gpu device info */
165 
166 	resource_size_t	mmio_base;
167 	resource_size_t	mmio_size;
168 	void __iomem	*mmio;
169 	uint32_t	int_reg;
170 
171 	struct drm_display_mode		mode;
172 	struct loongson_mode_info	mode_info[2];
173 	struct drm_gem_cma_object	*cursor;
174 
175 	int 			num_crtc;
176 	struct loongson_crtc 	lcrtc[MAX_CRTC];
177 	struct loongson_i2c	i2c_bus[DC_I2C_BUS_MAX];
178 
179 	void *vbios;
180 	struct list_head desc_list;
181 
182 	bool	inited;
183 	bool 	suspended;
184 	bool	cursor_showed;
185 	int	cursor_crtc_id;
186 
187 	int connector_active0;
188 	int connector_active1;
189 
190 	enum loongson_chip chip;
191 };
192 
193 extern spinlock_t loongson_reglock;
194 
195 /* FIXME: LS7A2000's switch_panel is not available, just return false. */
clone_mode(struct loongson_drm_device *ldev)196 static inline bool clone_mode(struct loongson_drm_device *ldev)
197 {
198 	return false;
199 
200 	if (ldev->num_crtc < 2)
201 		return true;
202 	if (ldev->mode_info[0].connector->base.status != connector_status_connected)
203 		return true;
204 	if (ldev->mode_info[1].connector->base.status != connector_status_connected)
205 		return true;
206 	if (ldev->lcrtc[0].base.x || ldev->lcrtc[0].base.y)
207 		return false;
208 	if (ldev->lcrtc[1].base.x || ldev->lcrtc[1].base.y)
209 		return false;
210 
211 	return true;
212 }
213 
214 int loongson_irq_enable_vblank(struct drm_device *dev,unsigned int crtc_id);
215 void loongson_irq_disable_vblank(struct drm_device *dev,unsigned int crtc_id);
216 irqreturn_t loongson_irq_handler(int irq,void *arg);
217 void loongson_irq_preinstall(struct drm_device *dev);
218 int loongson_irq_postinstall(struct drm_device *dev);
219 void loongson_irq_uninstall(struct drm_device *dev);
220 
221 u32 crtc_read(struct loongson_crtc *lcrtc, u32 offset);
222 void crtc_write(struct loongson_crtc *lcrtc, u32 offset, u32 val);
223 
224 int loongson_gpio_init(struct loongson_drm_device *ldev);
225 int loongson_crtc_init(struct loongson_drm_device *ldev);
226 struct drm_encoder *loongson_encoder_init(struct drm_device *dev, unsigned int index);
227 struct drm_connector *loongson_connector_init(struct drm_device *dev, unsigned int index);
228 
229 int loongson_fbdev_init(struct loongson_drm_device *ldev);
230 void loongson_fbdev_fini(struct loongson_drm_device *ldev);
231 void loongson_fbdev_restore_mode(struct loongson_drm_device *ldev);
232 
233 int loongson_drm_drm_suspend(struct drm_device *dev, bool suspend,
234                                    bool fbcon, bool freeze);
235 int loongson_drm_drm_resume(struct drm_device *dev, bool resume, bool fbcon);
236 		   /* loongson_cursor.c */
237 int loongson_crtc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file_priv,
238 					uint32_t handle, uint32_t width, uint32_t height, int32_t hot_x, int32_t hot_y);
239 int loongson_crtc_cursor_move(struct drm_crtc *crtc, int x, int y);
240 
241 #endif
242