1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Frame buffer driver for the Carmine GPU.
4 *
5 * The driver configures the GPU as follows
6 * - FB0 is display 0 with unique memory area
7 * - FB1 is display 1 with unique memory area
8 * - both display use 32 bit colors
9 */
10#include <linux/aperture.h>
11#include <linux/delay.h>
12#include <linux/errno.h>
13#include <linux/fb.h>
14#include <linux/interrupt.h>
15#include <linux/pci.h>
16#include <linux/slab.h>
17#include <linux/module.h>
18
19#include "carminefb.h"
20#include "carminefb_regs.h"
21
22#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
23#error  "The endianness of the target host has not been defined."
24#endif
25
26/*
27 * The initial video mode can be supplied via two different ways:
28 * - as a string that is passed to fb_find_mode() (module option fb_mode_str)
29 * - as an integer that picks the video mode from carmine_modedb[] (module
30 *   option fb_mode)
31 *
32 * If nothing is used than the initial video mode will be the
33 * CARMINEFB_DEFAULT_VIDEO_MODE member of the carmine_modedb[].
34 */
35#define CARMINEFB_DEFAULT_VIDEO_MODE	1
36
37static unsigned int fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
38module_param(fb_mode, uint, 0444);
39MODULE_PARM_DESC(fb_mode, "Initial video mode as integer.");
40
41static char *fb_mode_str;
42module_param(fb_mode_str, charp, 0444);
43MODULE_PARM_DESC(fb_mode_str, "Initial video mode in characters.");
44
45/*
46 * Carminefb displays:
47 * 0b000 None
48 * 0b001 Display 0
49 * 0b010 Display 1
50 */
51static int fb_displays = CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1;
52module_param(fb_displays, int, 0444);
53MODULE_PARM_DESC(fb_displays, "Bit mode, which displays are used");
54
55struct carmine_hw {
56	void __iomem *v_regs;
57	void __iomem *screen_mem;
58	struct fb_info *fb[MAX_DISPLAY];
59};
60
61struct carmine_resolution {
62	u32 htp;
63	u32 hsp;
64	u32 hsw;
65	u32 hdp;
66	u32 vtr;
67	u32 vsp;
68	u32 vsw;
69	u32 vdp;
70	u32 disp_mode;
71};
72
73struct carmine_fb {
74	void __iomem *display_reg;
75	void __iomem *screen_base;
76	u32 smem_offset;
77	u32 cur_mode;
78	u32 new_mode;
79	struct carmine_resolution *res;
80	u32 pseudo_palette[16];
81};
82
83static struct fb_fix_screeninfo carminefb_fix = {
84	.id = "Carmine",
85	.type = FB_TYPE_PACKED_PIXELS,
86	.visual = FB_VISUAL_TRUECOLOR,
87	.accel = FB_ACCEL_NONE,
88};
89
90static const struct fb_videomode carmine_modedb[] = {
91	{
92		.name		= "640x480",
93		.xres		= 640,
94		.yres		= 480,
95	}, {
96		.name		= "800x600",
97		.xres		= 800,
98		.yres		= 600,
99	},
100};
101
102static struct carmine_resolution car_modes[] = {
103	{
104		/* 640x480 */
105		.htp = 800,
106		.hsp = 672,
107		.hsw = 96,
108		.hdp = 640,
109		.vtr = 525,
110		.vsp = 490,
111		.vsw = 2,
112		.vdp = 480,
113		.disp_mode = 0x1400,
114	},
115	{
116		/* 800x600 */
117		.htp = 1060,
118		.hsp = 864,
119		.hsw = 72,
120		.hdp = 800,
121		.vtr = 628,
122		.vsp = 601,
123		.vsw = 2,
124		.vdp = 600,
125		.disp_mode = 0x0d00,
126	}
127};
128
129static int carmine_find_mode(const struct fb_var_screeninfo *var)
130{
131	int i;
132
133	for (i = 0; i < ARRAY_SIZE(car_modes); i++)
134		if (car_modes[i].hdp == var->xres &&
135		    car_modes[i].vdp == var->yres)
136			return i;
137	return -EINVAL;
138}
139
140static void c_set_disp_reg(const struct carmine_fb *par,
141		u32 offset, u32 val)
142{
143	writel(val, par->display_reg + offset);
144}
145
146static u32 c_get_disp_reg(const struct carmine_fb *par,
147		u32 offset)
148{
149	return readl(par->display_reg + offset);
150}
151
152static void c_set_hw_reg(const struct carmine_hw *hw,
153		u32 offset, u32 val)
154{
155	writel(val, hw->v_regs + offset);
156}
157
158static u32 c_get_hw_reg(const struct carmine_hw *hw,
159		u32 offset)
160{
161	return readl(hw->v_regs + offset);
162}
163
164static int carmine_setcolreg(unsigned regno, unsigned red, unsigned green,
165		unsigned blue, unsigned transp, struct fb_info *info)
166{
167	if (regno >= 16)
168		return 1;
169
170	red >>= 8;
171	green >>= 8;
172	blue >>= 8;
173	transp >>= 8;
174
175	((__be32 *)info->pseudo_palette)[regno] = cpu_to_be32(transp << 24 |
176		red << 0 | green << 8 | blue << 16);
177	return 0;
178}
179
180static int carmine_check_var(struct fb_var_screeninfo *var,
181		struct fb_info *info)
182{
183	int ret;
184
185	ret = carmine_find_mode(var);
186	if (ret < 0)
187		return ret;
188
189	if (var->grayscale || var->rotate || var->nonstd)
190		return -EINVAL;
191
192	var->xres_virtual = var->xres;
193	var->yres_virtual = var->yres;
194
195	var->bits_per_pixel = 32;
196
197#ifdef __BIG_ENDIAN
198	var->transp.offset = 24;
199	var->red.offset = 0;
200	var->green.offset = 8;
201	var->blue.offset = 16;
202#else
203	var->transp.offset = 24;
204	var->red.offset = 16;
205	var->green.offset = 8;
206	var->blue.offset = 0;
207#endif
208
209	var->red.length = 8;
210	var->green.length = 8;
211	var->blue.length = 8;
212	var->transp.length = 8;
213
214	var->red.msb_right = 0;
215	var->green.msb_right = 0;
216	var->blue.msb_right = 0;
217	var->transp.msb_right = 0;
218	return 0;
219}
220
221static void carmine_init_display_param(struct carmine_fb *par)
222{
223	u32 width;
224	u32 height;
225	u32 param;
226	u32 window_size;
227	u32 soffset = par->smem_offset;
228
229	c_set_disp_reg(par, CARMINE_DISP_REG_C_TRANS, 0);
230	c_set_disp_reg(par, CARMINE_DISP_REG_MLMR_TRANS, 0);
231	c_set_disp_reg(par, CARMINE_DISP_REG_CURSOR_MODE,
232			CARMINE_CURSOR0_PRIORITY_MASK |
233			CARMINE_CURSOR1_PRIORITY_MASK |
234			CARMINE_CURSOR_CUTZ_MASK);
235
236	/* Set default cursor position */
237	c_set_disp_reg(par, CARMINE_DISP_REG_CUR1_POS, 0 << 16 | 0);
238	c_set_disp_reg(par, CARMINE_DISP_REG_CUR2_POS, 0 << 16 | 0);
239
240	/* Set default display mode */
241	c_set_disp_reg(par, CARMINE_DISP_REG_L0_EXT_MODE, CARMINE_WINDOW_MODE |
242			CARMINE_EXT_CMODE_DIRECT24_RGBA);
243	c_set_disp_reg(par, CARMINE_DISP_REG_L1_EXT_MODE,
244			CARMINE_EXT_CMODE_DIRECT24_RGBA);
245	c_set_disp_reg(par, CARMINE_DISP_REG_L2_EXT_MODE, CARMINE_EXTEND_MODE |
246			CARMINE_EXT_CMODE_DIRECT24_RGBA);
247	c_set_disp_reg(par, CARMINE_DISP_REG_L3_EXT_MODE, CARMINE_EXTEND_MODE |
248			CARMINE_EXT_CMODE_DIRECT24_RGBA);
249	c_set_disp_reg(par, CARMINE_DISP_REG_L4_EXT_MODE, CARMINE_EXTEND_MODE |
250			CARMINE_EXT_CMODE_DIRECT24_RGBA);
251	c_set_disp_reg(par, CARMINE_DISP_REG_L5_EXT_MODE, CARMINE_EXTEND_MODE |
252			CARMINE_EXT_CMODE_DIRECT24_RGBA);
253	c_set_disp_reg(par, CARMINE_DISP_REG_L6_EXT_MODE, CARMINE_EXTEND_MODE |
254			CARMINE_EXT_CMODE_DIRECT24_RGBA);
255	c_set_disp_reg(par, CARMINE_DISP_REG_L7_EXT_MODE, CARMINE_EXTEND_MODE |
256			CARMINE_EXT_CMODE_DIRECT24_RGBA);
257
258	/* Set default frame size to layer mode register */
259	width = par->res->hdp * 4 / CARMINE_DISP_WIDTH_UNIT;
260	width = width << CARMINE_DISP_WIDTH_SHIFT;
261
262	height = par->res->vdp - 1;
263	param = width | height;
264
265	c_set_disp_reg(par, CARMINE_DISP_REG_L0_MODE_W_H, param);
266	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIDTH, width);
267	c_set_disp_reg(par, CARMINE_DISP_REG_L2_MODE_W_H, param);
268	c_set_disp_reg(par, CARMINE_DISP_REG_L3_MODE_W_H, param);
269	c_set_disp_reg(par, CARMINE_DISP_REG_L4_MODE_W_H, param);
270	c_set_disp_reg(par, CARMINE_DISP_REG_L5_MODE_W_H, param);
271	c_set_disp_reg(par, CARMINE_DISP_REG_L6_MODE_W_H, param);
272	c_set_disp_reg(par, CARMINE_DISP_REG_L7_MODE_W_H, param);
273
274	/* Set default pos and size */
275	window_size = (par->res->vdp - 1) << CARMINE_DISP_WIN_H_SHIFT;
276	window_size |= par->res->hdp;
277
278	c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_POS, 0);
279	c_set_disp_reg(par, CARMINE_DISP_REG_L0_WIN_SIZE, window_size);
280	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_POS, 0);
281	c_set_disp_reg(par, CARMINE_DISP_REG_L1_WIN_SIZE, window_size);
282	c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_POS, 0);
283	c_set_disp_reg(par, CARMINE_DISP_REG_L2_WIN_SIZE, window_size);
284	c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_POS, 0);
285	c_set_disp_reg(par, CARMINE_DISP_REG_L3_WIN_SIZE, window_size);
286	c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_POS, 0);
287	c_set_disp_reg(par, CARMINE_DISP_REG_L4_WIN_SIZE, window_size);
288	c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_POS, 0);
289	c_set_disp_reg(par, CARMINE_DISP_REG_L5_WIN_SIZE, window_size);
290	c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_POS, 0);
291	c_set_disp_reg(par, CARMINE_DISP_REG_L6_WIN_SIZE, window_size);
292	c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_POS, 0);
293	c_set_disp_reg(par, CARMINE_DISP_REG_L7_WIN_SIZE, window_size);
294
295	/* Set default origin address */
296	c_set_disp_reg(par, CARMINE_DISP_REG_L0_ORG_ADR, soffset);
297	c_set_disp_reg(par, CARMINE_DISP_REG_L1_ORG_ADR, soffset);
298	c_set_disp_reg(par, CARMINE_DISP_REG_L2_ORG_ADR1, soffset);
299	c_set_disp_reg(par, CARMINE_DISP_REG_L3_ORG_ADR1, soffset);
300	c_set_disp_reg(par, CARMINE_DISP_REG_L4_ORG_ADR1, soffset);
301	c_set_disp_reg(par, CARMINE_DISP_REG_L5_ORG_ADR1, soffset);
302	c_set_disp_reg(par, CARMINE_DISP_REG_L6_ORG_ADR1, soffset);
303	c_set_disp_reg(par, CARMINE_DISP_REG_L7_ORG_ADR1, soffset);
304
305	/* Set default display address */
306	c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_ADR, soffset);
307	c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_ADR1, soffset);
308	c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_ADR1, soffset);
309	c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_ADR1, soffset);
310	c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_ADR1, soffset);
311	c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_ADR0, soffset);
312	c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_ADR0, soffset);
313
314	/* Set default display position */
315	c_set_disp_reg(par, CARMINE_DISP_REG_L0_DISP_POS, 0);
316	c_set_disp_reg(par, CARMINE_DISP_REG_L2_DISP_POS, 0);
317	c_set_disp_reg(par, CARMINE_DISP_REG_L3_DISP_POS, 0);
318	c_set_disp_reg(par, CARMINE_DISP_REG_L4_DISP_POS, 0);
319	c_set_disp_reg(par, CARMINE_DISP_REG_L5_DISP_POS, 0);
320	c_set_disp_reg(par, CARMINE_DISP_REG_L6_DISP_POS, 0);
321	c_set_disp_reg(par, CARMINE_DISP_REG_L7_DISP_POS, 0);
322
323	/* Set default blend mode */
324	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L0, 0);
325	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L1, 0);
326	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L2, 0);
327	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L3, 0);
328	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L4, 0);
329	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L5, 0);
330	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L6, 0);
331	c_set_disp_reg(par, CARMINE_DISP_REG_BLEND_MODE_L7, 0);
332
333	/* default transparency mode */
334	c_set_disp_reg(par, CARMINE_DISP_REG_L0_TRANS, 0);
335	c_set_disp_reg(par, CARMINE_DISP_REG_L1_TRANS, 0);
336	c_set_disp_reg(par, CARMINE_DISP_REG_L2_TRANS, 0);
337	c_set_disp_reg(par, CARMINE_DISP_REG_L3_TRANS, 0);
338	c_set_disp_reg(par, CARMINE_DISP_REG_L4_TRANS, 0);
339	c_set_disp_reg(par, CARMINE_DISP_REG_L5_TRANS, 0);
340	c_set_disp_reg(par, CARMINE_DISP_REG_L6_TRANS, 0);
341	c_set_disp_reg(par, CARMINE_DISP_REG_L7_TRANS, 0);
342
343	/* Set default read skip parameter */
344	c_set_disp_reg(par, CARMINE_DISP_REG_L0RM, 0);
345	c_set_disp_reg(par, CARMINE_DISP_REG_L2RM, 0);
346	c_set_disp_reg(par, CARMINE_DISP_REG_L3RM, 0);
347	c_set_disp_reg(par, CARMINE_DISP_REG_L4RM, 0);
348	c_set_disp_reg(par, CARMINE_DISP_REG_L5RM, 0);
349	c_set_disp_reg(par, CARMINE_DISP_REG_L6RM, 0);
350	c_set_disp_reg(par, CARMINE_DISP_REG_L7RM, 0);
351
352	c_set_disp_reg(par, CARMINE_DISP_REG_L0PX, 0);
353	c_set_disp_reg(par, CARMINE_DISP_REG_L2PX, 0);
354	c_set_disp_reg(par, CARMINE_DISP_REG_L3PX, 0);
355	c_set_disp_reg(par, CARMINE_DISP_REG_L4PX, 0);
356	c_set_disp_reg(par, CARMINE_DISP_REG_L5PX, 0);
357	c_set_disp_reg(par, CARMINE_DISP_REG_L6PX, 0);
358	c_set_disp_reg(par, CARMINE_DISP_REG_L7PX, 0);
359
360	c_set_disp_reg(par, CARMINE_DISP_REG_L0PY, 0);
361	c_set_disp_reg(par, CARMINE_DISP_REG_L2PY, 0);
362	c_set_disp_reg(par, CARMINE_DISP_REG_L3PY, 0);
363	c_set_disp_reg(par, CARMINE_DISP_REG_L4PY, 0);
364	c_set_disp_reg(par, CARMINE_DISP_REG_L5PY, 0);
365	c_set_disp_reg(par, CARMINE_DISP_REG_L6PY, 0);
366	c_set_disp_reg(par, CARMINE_DISP_REG_L7PY, 0);
367}
368
369static void set_display_parameters(struct carmine_fb *par)
370{
371	u32 mode;
372	u32 hdp, vdp, htp, hsp, hsw, vtr, vsp, vsw;
373
374	/*
375	 * display timing. Parameters are decreased by one because hardware
376	 * spec is 0 to (n - 1)
377	 * */
378	hdp = par->res->hdp - 1;
379	vdp = par->res->vdp - 1;
380	htp = par->res->htp - 1;
381	hsp = par->res->hsp - 1;
382	hsw = par->res->hsw - 1;
383	vtr = par->res->vtr - 1;
384	vsp = par->res->vsp - 1;
385	vsw = par->res->vsw - 1;
386
387	c_set_disp_reg(par, CARMINE_DISP_REG_H_TOTAL,
388			htp << CARMINE_DISP_HTP_SHIFT);
389	c_set_disp_reg(par, CARMINE_DISP_REG_H_PERIOD,
390			(hdp << CARMINE_DISP_HDB_SHIFT)	| hdp);
391	c_set_disp_reg(par, CARMINE_DISP_REG_V_H_W_H_POS,
392			(vsw << CARMINE_DISP_VSW_SHIFT) |
393			(hsw << CARMINE_DISP_HSW_SHIFT) |
394			(hsp));
395	c_set_disp_reg(par, CARMINE_DISP_REG_V_TOTAL,
396			vtr << CARMINE_DISP_VTR_SHIFT);
397	c_set_disp_reg(par, CARMINE_DISP_REG_V_PERIOD_POS,
398			(vdp << CARMINE_DISP_VDP_SHIFT) | vsp);
399
400	/* clock */
401	mode = c_get_disp_reg(par, CARMINE_DISP_REG_DCM1);
402	mode = (mode & ~CARMINE_DISP_DCM_MASK) |
403		(par->res->disp_mode & CARMINE_DISP_DCM_MASK);
404	/* enable video output and layer 0 */
405	mode |= CARMINE_DEN | CARMINE_L0E;
406	c_set_disp_reg(par, CARMINE_DISP_REG_DCM1, mode);
407}
408
409static int carmine_set_par(struct fb_info *info)
410{
411	struct carmine_fb *par = info->par;
412	int ret;
413
414	ret = carmine_find_mode(&info->var);
415	if (ret < 0)
416		return ret;
417
418	par->new_mode = ret;
419	if (par->cur_mode != par->new_mode) {
420
421		par->cur_mode = par->new_mode;
422		par->res = &car_modes[par->new_mode];
423
424		carmine_init_display_param(par);
425		set_display_parameters(par);
426	}
427
428	info->fix.line_length = info->var.xres * info->var.bits_per_pixel / 8;
429	return 0;
430}
431
432static int init_hardware(struct carmine_hw *hw)
433{
434	u32 flags;
435	u32 loops;
436	u32 ret;
437
438	/* Initialize Carmine */
439	/* Sets internal clock */
440	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE,
441			CARMINE_DFLT_IP_CLOCK_ENABLE);
442
443	/* Video signal output is turned off */
444	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
445	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
446
447	/* Software reset */
448	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 1);
449	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_SOFTWARE_RESET, 0);
450
451	/* I/O mode settings */
452	flags = CARMINE_DFLT_IP_DCTL_IO_CONT1 << 16 |
453		CARMINE_DFLT_IP_DCTL_IO_CONT0;
454	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_IOCONT1_IOCONT0,
455			flags);
456
457	/* DRAM initial sequence */
458	flags = CARMINE_DFLT_IP_DCTL_MODE << 16 | CARMINE_DFLT_IP_DCTL_ADD;
459	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD,
460			flags);
461
462	flags = CARMINE_DFLT_IP_DCTL_SET_TIME1 << 16 |
463		CARMINE_DFLT_IP_DCTL_EMODE;
464	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_SETTIME1_EMODE,
465			flags);
466
467	flags = CARMINE_DFLT_IP_DCTL_REFRESH << 16 |
468		CARMINE_DFLT_IP_DCTL_SET_TIME2;
469	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_REFRESH_SETTIME2,
470			flags);
471
472	flags = CARMINE_DFLT_IP_DCTL_RESERVE2 << 16 |
473		CARMINE_DFLT_IP_DCTL_FIFO_DEPTH;
474	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV2_RSV1, flags);
475
476	flags = CARMINE_DFLT_IP_DCTL_DDRIF2 << 16 | CARMINE_DFLT_IP_DCTL_DDRIF1;
477	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_DDRIF2_DDRIF1,
478			flags);
479
480	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
481		CARMINE_DFLT_IP_DCTL_STATES;
482	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
483			flags);
484
485	/* Executes DLL reset */
486	if (CARMINE_DCTL_DLL_RESET) {
487		for (loops = 0; loops < CARMINE_DCTL_INIT_WAIT_LIMIT; loops++) {
488
489			ret = c_get_hw_reg(hw, CARMINE_DCTL_REG +
490					CARMINE_DCTL_REG_RSV0_STATES);
491			ret &= CARMINE_DCTL_REG_STATES_MASK;
492			if (!ret)
493				break;
494
495			mdelay(CARMINE_DCTL_INIT_WAIT_INTERVAL);
496		}
497
498		if (loops >= CARMINE_DCTL_INIT_WAIT_LIMIT) {
499			printk(KERN_ERR "DRAM init failed\n");
500			return -EIO;
501		}
502	}
503
504	flags = CARMINE_DFLT_IP_DCTL_MODE_AFT_RST << 16 |
505		CARMINE_DFLT_IP_DCTL_ADD;
506	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_MODE_ADD, flags);
507
508	flags = CARMINE_DFLT_IP_DCTL_RESERVE0 << 16 |
509		CARMINE_DFLT_IP_DCTL_STATES_AFT_RST;
510	c_set_hw_reg(hw, CARMINE_DCTL_REG + CARMINE_DCTL_REG_RSV0_STATES,
511			flags);
512
513	/* Initialize the write back register */
514	c_set_hw_reg(hw, CARMINE_WB_REG + CARMINE_WB_REG_WBM,
515			CARMINE_WB_REG_WBM_DEFAULT);
516
517	/* Initialize the Kottos registers */
518	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRINTM, 0);
519	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_VRERRM, 0);
520
521	/* Set DC offsets */
522	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PX, 0);
523	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_PY, 0);
524	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LX, 0);
525	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_LY, 0);
526	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TX, 0);
527	c_set_hw_reg(hw, CARMINE_GRAPH_REG + CARMINE_GRAPH_REG_DC_OFFSET_TY, 0);
528	return 0;
529}
530
531static const struct fb_ops carminefb_ops = {
532	.owner		= THIS_MODULE,
533	FB_DEFAULT_IOMEM_OPS,
534	.fb_check_var	= carmine_check_var,
535	.fb_set_par	= carmine_set_par,
536	.fb_setcolreg	= carmine_setcolreg,
537};
538
539static int alloc_carmine_fb(void __iomem *regs, void __iomem *smem_base,
540			    int smem_offset, struct device *device,
541			    struct fb_info **rinfo)
542{
543	int ret;
544	struct fb_info *info;
545	struct carmine_fb *par;
546
547	info = framebuffer_alloc(sizeof *par, device);
548	if (!info)
549		return -ENOMEM;
550
551	par = info->par;
552	par->display_reg = regs;
553	par->smem_offset = smem_offset;
554
555	info->screen_base = smem_base + smem_offset;
556	info->screen_size = CARMINE_DISPLAY_MEM;
557	info->fbops = &carminefb_ops;
558
559	info->fix = carminefb_fix;
560	info->pseudo_palette = par->pseudo_palette;
561
562	ret = fb_alloc_cmap(&info->cmap, 256, 1);
563	if (ret < 0)
564		goto err_free_fb;
565
566	if (fb_mode >= ARRAY_SIZE(carmine_modedb))
567		fb_mode = CARMINEFB_DEFAULT_VIDEO_MODE;
568
569	par->cur_mode = par->new_mode = ~0;
570
571	ret = fb_find_mode(&info->var, info, fb_mode_str, carmine_modedb,
572			ARRAY_SIZE(carmine_modedb),
573			&carmine_modedb[fb_mode], 32);
574	if (!ret || ret == 4) {
575		ret = -EINVAL;
576		goto err_dealloc_cmap;
577	}
578
579	fb_videomode_to_modelist(carmine_modedb, ARRAY_SIZE(carmine_modedb),
580			&info->modelist);
581
582	ret = register_framebuffer(info);
583	if (ret < 0)
584		goto err_dealloc_cmap;
585
586	fb_info(info, "%s frame buffer device\n", info->fix.id);
587
588	*rinfo = info;
589	return 0;
590
591err_dealloc_cmap:
592	fb_dealloc_cmap(&info->cmap);
593err_free_fb:
594	framebuffer_release(info);
595	return ret;
596}
597
598static void cleanup_fb_device(struct fb_info *info)
599{
600	if (info) {
601		unregister_framebuffer(info);
602		fb_dealloc_cmap(&info->cmap);
603		framebuffer_release(info);
604	}
605}
606
607static int carminefb_probe(struct pci_dev *dev, const struct pci_device_id *ent)
608{
609	struct carmine_hw *hw;
610	struct device *device = &dev->dev;
611	struct fb_info *info;
612	int ret;
613
614	ret = aperture_remove_conflicting_pci_devices(dev, "carminefb");
615	if (ret)
616		return ret;
617
618	ret = pci_enable_device(dev);
619	if (ret)
620		return ret;
621
622	ret = -ENOMEM;
623	hw = kzalloc(sizeof *hw, GFP_KERNEL);
624	if (!hw)
625		goto err_enable_pci;
626
627	carminefb_fix.mmio_start = pci_resource_start(dev, CARMINE_CONFIG_BAR);
628	carminefb_fix.mmio_len = pci_resource_len(dev, CARMINE_CONFIG_BAR);
629
630	if (!request_mem_region(carminefb_fix.mmio_start,
631				carminefb_fix.mmio_len,
632				"carminefb regbase")) {
633		printk(KERN_ERR "carminefb: Can't reserve regbase.\n");
634		ret = -EBUSY;
635		goto err_free_hw;
636	}
637	hw->v_regs = ioremap(carminefb_fix.mmio_start,
638			carminefb_fix.mmio_len);
639	if (!hw->v_regs) {
640		printk(KERN_ERR "carminefb: Can't remap %s register.\n",
641				carminefb_fix.id);
642		goto err_free_reg_mmio;
643	}
644
645	carminefb_fix.smem_start = pci_resource_start(dev, CARMINE_MEMORY_BAR);
646	carminefb_fix.smem_len = pci_resource_len(dev, CARMINE_MEMORY_BAR);
647
648	/* The memory area tends to be very large (256 MiB). Remap only what
649	 * is required for that largest resolution to avoid remaps at run
650	 * time
651	 */
652	if (carminefb_fix.smem_len > CARMINE_TOTAL_DIPLAY_MEM)
653		carminefb_fix.smem_len = CARMINE_TOTAL_DIPLAY_MEM;
654
655	else if (carminefb_fix.smem_len < CARMINE_TOTAL_DIPLAY_MEM) {
656		printk(KERN_ERR "carminefb: Memory bar is only %d bytes, %d "
657				"are required.", carminefb_fix.smem_len,
658				CARMINE_TOTAL_DIPLAY_MEM);
659		goto err_unmap_vregs;
660	}
661
662	if (!request_mem_region(carminefb_fix.smem_start,
663				carminefb_fix.smem_len,	"carminefb smem")) {
664		printk(KERN_ERR "carminefb: Can't reserve smem.\n");
665		goto err_unmap_vregs;
666	}
667
668	hw->screen_mem = ioremap(carminefb_fix.smem_start,
669			carminefb_fix.smem_len);
670	if (!hw->screen_mem) {
671		printk(KERN_ERR "carmine: Can't ioremap smem area.\n");
672		goto err_reg_smem;
673	}
674
675	ret = init_hardware(hw);
676	if (ret)
677		goto err_unmap_screen;
678
679	info = NULL;
680	if (fb_displays & CARMINE_USE_DISPLAY0) {
681		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP0_REG,
682				hw->screen_mem, CARMINE_DISPLAY_MEM * 0,
683				device, &info);
684		if (ret)
685			goto err_deinit_hw;
686	}
687
688	hw->fb[0] = info;
689
690	info = NULL;
691	if (fb_displays & CARMINE_USE_DISPLAY1) {
692		ret = alloc_carmine_fb(hw->v_regs + CARMINE_DISP1_REG,
693				hw->screen_mem, CARMINE_DISPLAY_MEM * 1,
694				device, &info);
695		if (ret)
696			goto err_cleanup_fb0;
697	}
698
699	hw->fb[1] = info;
700	info = NULL;
701
702	pci_set_drvdata(dev, hw);
703	return 0;
704
705err_cleanup_fb0:
706	cleanup_fb_device(hw->fb[0]);
707err_deinit_hw:
708	/* disable clock, etc */
709	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
710err_unmap_screen:
711	iounmap(hw->screen_mem);
712err_reg_smem:
713	release_mem_region(carminefb_fix.smem_start, carminefb_fix.smem_len);
714err_unmap_vregs:
715	iounmap(hw->v_regs);
716err_free_reg_mmio:
717	release_mem_region(carminefb_fix.mmio_start, carminefb_fix.mmio_len);
718err_free_hw:
719	kfree(hw);
720err_enable_pci:
721	pci_disable_device(dev);
722	return ret;
723}
724
725static void carminefb_remove(struct pci_dev *dev)
726{
727	struct carmine_hw *hw = pci_get_drvdata(dev);
728	struct fb_fix_screeninfo fix;
729	int i;
730
731	/* in case we use only fb1 and not fb1 */
732	if (hw->fb[0])
733		fix = hw->fb[0]->fix;
734	else
735		fix = hw->fb[1]->fix;
736
737	/* deactivate display(s) and switch clocks */
738	c_set_hw_reg(hw, CARMINE_DISP0_REG + CARMINE_DISP_REG_DCM1, 0);
739	c_set_hw_reg(hw, CARMINE_DISP1_REG + CARMINE_DISP_REG_DCM1, 0);
740	c_set_hw_reg(hw, CARMINE_CTL_REG + CARMINE_CTL_REG_CLOCK_ENABLE, 0);
741
742	for (i = 0; i < MAX_DISPLAY; i++)
743		cleanup_fb_device(hw->fb[i]);
744
745	iounmap(hw->screen_mem);
746	release_mem_region(fix.smem_start, fix.smem_len);
747	iounmap(hw->v_regs);
748	release_mem_region(fix.mmio_start, fix.mmio_len);
749
750	pci_disable_device(dev);
751	kfree(hw);
752}
753
754#define PCI_VENDOR_ID_FUJITU_LIMITED 0x10cf
755static struct pci_device_id carmine_devices[] = {
756{
757	PCI_DEVICE(PCI_VENDOR_ID_FUJITU_LIMITED, 0x202b)},
758	{0, 0, 0, 0, 0, 0, 0}
759};
760
761MODULE_DEVICE_TABLE(pci, carmine_devices);
762
763static struct pci_driver carmine_pci_driver = {
764	.name		= "carminefb",
765	.id_table	= carmine_devices,
766	.probe		= carminefb_probe,
767	.remove		= carminefb_remove,
768};
769
770static int __init carminefb_init(void)
771{
772	if (fb_modesetting_disabled("carminefb"))
773		return -ENODEV;
774
775	if (!(fb_displays &
776		(CARMINE_USE_DISPLAY0 | CARMINE_USE_DISPLAY1))) {
777		printk(KERN_ERR "If you disable both displays than you don't "
778				"need the driver at all\n");
779		return -EINVAL;
780	}
781	return pci_register_driver(&carmine_pci_driver);
782}
783module_init(carminefb_init);
784
785static void __exit carminefb_cleanup(void)
786{
787	pci_unregister_driver(&carmine_pci_driver);
788}
789module_exit(carminefb_cleanup);
790
791MODULE_AUTHOR("Sebastian Siewior <bigeasy@linutronix.de>");
792MODULE_DESCRIPTION("Framebuffer driver for Fujitsu Carmine based devices");
793MODULE_LICENSE("GPL v2");
794