1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * ATI Frame Buffer Device Driver Core Definitions |
4 | */ |
5 | |
6 | #include <linux/io.h> |
7 | #include <linux/spinlock.h> |
8 | #include <linux/wait.h> |
9 | |
10 | /* |
11 | * Elements of the hardware specific atyfb_par structure |
12 | */ |
13 | |
14 | struct crtc { |
15 | u32 vxres; |
16 | u32 vyres; |
17 | u32 xoffset; |
18 | u32 yoffset; |
19 | u32 bpp; |
20 | u32 h_tot_disp; |
21 | u32 h_sync_strt_wid; |
22 | u32 v_tot_disp; |
23 | u32 v_sync_strt_wid; |
24 | u32 vline_crnt_vline; |
25 | u32 off_pitch; |
26 | u32 gen_cntl; |
27 | u32 dp_pix_width; /* acceleration */ |
28 | u32 dp_chain_mask; /* acceleration */ |
29 | #ifdef CONFIG_FB_ATY_GENERIC_LCD |
30 | u32 horz_stretching; |
31 | u32 vert_stretching; |
32 | u32 ext_vert_stretch; |
33 | u32 shadow_h_tot_disp; |
34 | u32 shadow_h_sync_strt_wid; |
35 | u32 shadow_v_tot_disp; |
36 | u32 shadow_v_sync_strt_wid; |
37 | u32 lcd_gen_cntl; |
38 | u32 lcd_config_panel; |
39 | u32 lcd_index; |
40 | #endif |
41 | }; |
42 | |
43 | struct aty_interrupt { |
44 | wait_queue_head_t wait; |
45 | unsigned int count; |
46 | int pan_display; |
47 | }; |
48 | |
49 | struct pll_info { |
50 | int pll_max; |
51 | int pll_min; |
52 | int sclk, mclk, mclk_pm, xclk; |
53 | int ref_div; |
54 | int ref_clk; |
55 | int ecp_max; |
56 | }; |
57 | |
58 | typedef struct { |
59 | u16 unknown1; |
60 | u16 PCLK_min_freq; |
61 | u16 PCLK_max_freq; |
62 | u16 unknown2; |
63 | u16 ref_freq; |
64 | u16 ref_divider; |
65 | u16 unknown3; |
66 | u16 MCLK_pwd; |
67 | u16 MCLK_max_freq; |
68 | u16 XCLK_max_freq; |
69 | u16 SCLK_freq; |
70 | } __attribute__ ((packed)) PLL_BLOCK_MACH64; |
71 | |
72 | struct pll_514 { |
73 | u8 m; |
74 | u8 n; |
75 | }; |
76 | |
77 | struct pll_18818 { |
78 | u32 program_bits; |
79 | u32 locationAddr; |
80 | u32 period_in_ps; |
81 | u32 post_divider; |
82 | }; |
83 | |
84 | struct pll_ct { |
85 | u8 pll_ref_div; |
86 | u8 pll_gen_cntl; |
87 | u8 mclk_fb_div; |
88 | u8 mclk_fb_mult; /* 2 ro 4 */ |
89 | u8 sclk_fb_div; |
90 | u8 pll_vclk_cntl; |
91 | u8 vclk_post_div; |
92 | u8 vclk_fb_div; |
93 | u8 pll_ext_cntl; |
94 | u8 ext_vpll_cntl; |
95 | u8 spll_cntl2; |
96 | u32 dsp_config; /* Mach64 GTB DSP */ |
97 | u32 dsp_on_off; /* Mach64 GTB DSP */ |
98 | u32 dsp_loop_latency; |
99 | u32 fifo_size; |
100 | u32 xclkpagefaultdelay; |
101 | u32 xclkmaxrasdelay; |
102 | u8 xclk_ref_div; |
103 | u8 xclk_post_div; |
104 | u8 mclk_post_div_real; |
105 | u8 xclk_post_div_real; |
106 | u8 vclk_post_div_real; |
107 | u8 features; |
108 | #ifdef CONFIG_FB_ATY_GENERIC_LCD |
109 | u32 xres; /* use for LCD stretching/scaling */ |
110 | #endif |
111 | }; |
112 | |
113 | /* |
114 | for pll_ct.features |
115 | */ |
116 | #define DONT_USE_SPLL 0x1 |
117 | #define DONT_USE_XDLL 0x2 |
118 | #define USE_CPUCLK 0x4 |
119 | #define POWERDOWN_PLL 0x8 |
120 | |
121 | union aty_pll { |
122 | struct pll_ct ct; |
123 | struct pll_514 ibm514; |
124 | struct pll_18818 ics2595; |
125 | }; |
126 | |
127 | /* |
128 | * The hardware parameters for each card |
129 | */ |
130 | |
131 | struct atyfb_par { |
132 | u32 pseudo_palette[16]; |
133 | struct { u8 red, green, blue; } palette[256]; |
134 | const struct aty_dac_ops *dac_ops; |
135 | const struct aty_pll_ops *pll_ops; |
136 | void __iomem *ati_regbase; |
137 | unsigned long clk_wr_offset; /* meaning overloaded, clock id by CT */ |
138 | struct crtc crtc; |
139 | union aty_pll pll; |
140 | struct pll_info pll_limits; |
141 | u32 features; |
142 | u32 ref_clk_per; |
143 | u32 pll_per; |
144 | u32 mclk_per; |
145 | u32 xclk_per; |
146 | u8 bus_type; |
147 | u8 ram_type; |
148 | u8 mem_refresh_rate; |
149 | u16 pci_id; |
150 | u32 accel_flags; |
151 | int blitter_may_be_busy; |
152 | unsigned fifo_space; |
153 | int asleep; |
154 | int lock_blank; |
155 | unsigned long res_start; |
156 | unsigned long res_size; |
157 | struct pci_dev *pdev; |
158 | #ifdef __sparc__ |
159 | struct pci_mmap_map *mmap_map; |
160 | u8 mmaped; |
161 | #endif |
162 | int open; |
163 | #ifdef CONFIG_FB_ATY_GENERIC_LCD |
164 | unsigned long bios_base_phys; |
165 | unsigned long bios_base; |
166 | unsigned long lcd_table; |
167 | u16 lcd_width; |
168 | u16 lcd_height; |
169 | u32 lcd_pixclock; |
170 | u16 lcd_refreshrate; |
171 | u16 lcd_htotal; |
172 | u16 lcd_hdisp; |
173 | u16 lcd_hsync_dly; |
174 | u16 lcd_hsync_len; |
175 | u16 lcd_vtotal; |
176 | u16 lcd_vdisp; |
177 | u16 lcd_vsync_len; |
178 | u16 lcd_right_margin; |
179 | u16 lcd_lower_margin; |
180 | u16 lcd_hblank_len; |
181 | u16 lcd_vblank_len; |
182 | #endif |
183 | unsigned long aux_start; /* auxiliary aperture */ |
184 | unsigned long aux_size; |
185 | struct aty_interrupt vblank; |
186 | unsigned long irq_flags; |
187 | unsigned int irq; |
188 | spinlock_t int_lock; |
189 | int wc_cookie; |
190 | u32 mem_cntl; |
191 | struct crtc saved_crtc; |
192 | union aty_pll saved_pll; |
193 | }; |
194 | |
195 | /* |
196 | * ATI Mach64 features |
197 | */ |
198 | |
199 | #define M64_HAS(feature) ((par)->features & (M64F_##feature)) |
200 | |
201 | #define M64F_RESET_3D 0x00000001 |
202 | #define M64F_MAGIC_FIFO 0x00000002 |
203 | #define M64F_GTB_DSP 0x00000004 |
204 | #define M64F_FIFO_32 0x00000008 |
205 | #define M64F_SDRAM_MAGIC_PLL 0x00000010 |
206 | #define M64F_MAGIC_POSTDIV 0x00000020 |
207 | #define M64F_INTEGRATED 0x00000040 |
208 | #define M64F_CT_BUS 0x00000080 |
209 | #define M64F_VT_BUS 0x00000100 |
210 | #define M64F_MOBIL_BUS 0x00000200 |
211 | #define M64F_GX 0x00000400 |
212 | #define M64F_CT 0x00000800 |
213 | #define M64F_VT 0x00001000 |
214 | #define M64F_GT 0x00002000 |
215 | #define M64F_MAGIC_VRAM_SIZE 0x00004000 |
216 | #define M64F_G3_PB_1_1 0x00008000 |
217 | #define M64F_G3_PB_1024x768 0x00010000 |
218 | #define 0x00020000 |
219 | #define M64F_LT_LCD_REGS 0x00040000 |
220 | #define M64F_XL_DLL 0x00080000 |
221 | #define M64F_MFB_FORCE_4 0x00100000 |
222 | #define M64F_HW_TRIPLE 0x00200000 |
223 | #define M64F_XL_MEM 0x00400000 |
224 | /* |
225 | * Register access |
226 | */ |
227 | |
228 | static inline u32 aty_ld_le32(int regindex, const struct atyfb_par *par) |
229 | { |
230 | /* Hack for bloc 1, should be cleanly optimized by compiler */ |
231 | if (regindex >= 0x400) |
232 | regindex -= 0x800; |
233 | |
234 | #ifdef CONFIG_ATARI |
235 | return in_le32(par->ati_regbase + regindex); |
236 | #else |
237 | return readl(addr: par->ati_regbase + regindex); |
238 | #endif |
239 | } |
240 | |
241 | static inline void aty_st_le32(int regindex, u32 val, const struct atyfb_par *par) |
242 | { |
243 | /* Hack for bloc 1, should be cleanly optimized by compiler */ |
244 | if (regindex >= 0x400) |
245 | regindex -= 0x800; |
246 | |
247 | #ifdef CONFIG_ATARI |
248 | out_le32(par->ati_regbase + regindex, val); |
249 | #else |
250 | writel(val, addr: par->ati_regbase + regindex); |
251 | #endif |
252 | } |
253 | |
254 | static inline void aty_st_le16(int regindex, u16 val, |
255 | const struct atyfb_par *par) |
256 | { |
257 | /* Hack for bloc 1, should be cleanly optimized by compiler */ |
258 | if (regindex >= 0x400) |
259 | regindex -= 0x800; |
260 | #ifdef CONFIG_ATARI |
261 | out_le16(par->ati_regbase + regindex, val); |
262 | #else |
263 | writel(val, addr: par->ati_regbase + regindex); |
264 | #endif |
265 | } |
266 | |
267 | static inline u8 aty_ld_8(int regindex, const struct atyfb_par *par) |
268 | { |
269 | /* Hack for bloc 1, should be cleanly optimized by compiler */ |
270 | if (regindex >= 0x400) |
271 | regindex -= 0x800; |
272 | #ifdef CONFIG_ATARI |
273 | return in_8(par->ati_regbase + regindex); |
274 | #else |
275 | return readb(addr: par->ati_regbase + regindex); |
276 | #endif |
277 | } |
278 | |
279 | static inline void aty_st_8(int regindex, u8 val, const struct atyfb_par *par) |
280 | { |
281 | /* Hack for bloc 1, should be cleanly optimized by compiler */ |
282 | if (regindex >= 0x400) |
283 | regindex -= 0x800; |
284 | |
285 | #ifdef CONFIG_ATARI |
286 | out_8(par->ati_regbase + regindex, val); |
287 | #else |
288 | writeb(val, addr: par->ati_regbase + regindex); |
289 | #endif |
290 | } |
291 | |
292 | extern void aty_st_lcd(int index, u32 val, const struct atyfb_par *par); |
293 | extern u32 aty_ld_lcd(int index, const struct atyfb_par *par); |
294 | |
295 | /* |
296 | * DAC operations |
297 | */ |
298 | |
299 | struct aty_dac_ops { |
300 | int (*set_dac) (const struct fb_info * info, |
301 | const union aty_pll * pll, u32 bpp, u32 accel); |
302 | }; |
303 | |
304 | extern const struct aty_dac_ops aty_dac_ibm514; /* IBM RGB514 */ |
305 | extern const struct aty_dac_ops aty_dac_ati68860b; /* ATI 68860-B */ |
306 | extern const struct aty_dac_ops aty_dac_att21c498; /* AT&T 21C498 */ |
307 | extern const struct aty_dac_ops aty_dac_unsupported; /* unsupported */ |
308 | extern const struct aty_dac_ops aty_dac_ct; /* Integrated */ |
309 | |
310 | |
311 | /* |
312 | * Clock operations |
313 | */ |
314 | |
315 | struct aty_pll_ops { |
316 | int (*var_to_pll) (const struct fb_info * info, u32 vclk_per, u32 bpp, union aty_pll * pll); |
317 | u32 (*pll_to_var) (const struct fb_info * info, const union aty_pll * pll); |
318 | void (*set_pll) (const struct fb_info * info, const union aty_pll * pll); |
319 | void (*get_pll) (const struct fb_info *info, union aty_pll * pll); |
320 | int (*init_pll) (const struct fb_info * info, union aty_pll * pll); |
321 | void (*resume_pll)(const struct fb_info *info, union aty_pll *pll); |
322 | }; |
323 | |
324 | extern const struct aty_pll_ops aty_pll_ati18818_1; /* ATI 18818 */ |
325 | extern const struct aty_pll_ops aty_pll_stg1703; /* STG 1703 */ |
326 | extern const struct aty_pll_ops aty_pll_ch8398; /* Chrontel 8398 */ |
327 | extern const struct aty_pll_ops aty_pll_att20c408; /* AT&T 20C408 */ |
328 | extern const struct aty_pll_ops aty_pll_ibm514; /* IBM RGB514 */ |
329 | extern const struct aty_pll_ops aty_pll_unsupported; /* unsupported */ |
330 | extern const struct aty_pll_ops aty_pll_ct; /* Integrated */ |
331 | |
332 | |
333 | extern void aty_set_pll_ct(const struct fb_info *info, const union aty_pll *pll); |
334 | extern u8 aty_ld_pll_ct(int offset, const struct atyfb_par *par); |
335 | |
336 | extern const u8 aty_postdividers[8]; |
337 | |
338 | |
339 | /* |
340 | * Hardware cursor support |
341 | */ |
342 | |
343 | extern int aty_init_cursor(struct fb_info *info, struct fb_ops *atyfb_ops); |
344 | |
345 | /* |
346 | * Hardware acceleration |
347 | */ |
348 | |
349 | static inline void wait_for_fifo(u16 entries, struct atyfb_par *par) |
350 | { |
351 | unsigned fifo_space = par->fifo_space; |
352 | while (entries > fifo_space) { |
353 | fifo_space = 16 - fls(x: aty_ld_le32(FIFO_STAT, par) & 0xffff); |
354 | } |
355 | par->fifo_space = fifo_space - entries; |
356 | } |
357 | |
358 | static inline void wait_for_idle(struct atyfb_par *par) |
359 | { |
360 | wait_for_fifo(entries: 16, par); |
361 | while ((aty_ld_le32(GUI_STAT, par) & 1) != 0); |
362 | par->blitter_may_be_busy = 0; |
363 | } |
364 | |
365 | extern void aty_reset_engine(struct atyfb_par *par); |
366 | extern void aty_init_engine(struct atyfb_par *par, struct fb_info *info); |
367 | |
368 | void atyfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); |
369 | void atyfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); |
370 | void atyfb_imageblit(struct fb_info *info, const struct fb_image *image); |
371 | |
372 | |