xref: /openbmc/linux/drivers/video/fbdev/broadsheetfb.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1  /*
2   * broadsheetfb.c -- FB driver for E-Ink Broadsheet controller
3   *
4   * Copyright (C) 2008, Jaya Kumar
5   *
6   * This file is subject to the terms and conditions of the GNU General Public
7   * License. See the file COPYING in the main directory of this archive for
8   * more details.
9   *
10   * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
11   *
12   * This driver is written to be used with the Broadsheet display controller.
13   *
14   * It is intended to be architecture independent. A board specific driver
15   * must be used to perform all the physical IO interactions.
16   *
17   */
18  
19  #include <linux/module.h>
20  #include <linux/kernel.h>
21  #include <linux/errno.h>
22  #include <linux/string.h>
23  #include <linux/mm.h>
24  #include <linux/slab.h>
25  #include <linux/vmalloc.h>
26  #include <linux/delay.h>
27  #include <linux/interrupt.h>
28  #include <linux/fb.h>
29  #include <linux/init.h>
30  #include <linux/platform_device.h>
31  #include <linux/list.h>
32  #include <linux/firmware.h>
33  #include <linux/uaccess.h>
34  
35  #include <video/broadsheetfb.h>
36  
37  /* track panel specific parameters */
38  struct panel_info {
39  	int w;
40  	int h;
41  	u16 sdcfg;
42  	u16 gdcfg;
43  	u16 lutfmt;
44  	u16 fsynclen;
45  	u16 fendfbegin;
46  	u16 lsynclen;
47  	u16 lendlbegin;
48  	u16 pixclk;
49  };
50  
51  /* table of panel specific parameters to be indexed into by the board drivers */
52  static struct panel_info panel_table[] = {
53  	{	/* standard 6" on TFT backplane */
54  		.w = 800,
55  		.h = 600,
56  		.sdcfg = (100 | (1 << 8) | (1 << 9)),
57  		.gdcfg = 2,
58  		.lutfmt = (4 | (1 << 7)),
59  		.fsynclen = 4,
60  		.fendfbegin = (10 << 8) | 4,
61  		.lsynclen = 10,
62  		.lendlbegin = (100 << 8) | 4,
63  		.pixclk = 6,
64  	},
65  	{	/* custom 3.7" flexible on PET or steel */
66  		.w = 320,
67  		.h = 240,
68  		.sdcfg = (67 | (0 << 8) | (0 << 9) | (0 << 10) | (0 << 12)),
69  		.gdcfg = 3,
70  		.lutfmt = (4 | (1 << 7)),
71  		.fsynclen = 0,
72  		.fendfbegin = (80 << 8) | 4,
73  		.lsynclen = 10,
74  		.lendlbegin = (80 << 8) | 20,
75  		.pixclk = 14,
76  	},
77  	{	/* standard 9.7" on TFT backplane */
78  		.w = 1200,
79  		.h = 825,
80  		.sdcfg = (100 | (1 << 8) | (1 << 9) | (0 << 10) | (0 << 12)),
81  		.gdcfg = 2,
82  		.lutfmt = (4 | (1 << 7)),
83  		.fsynclen = 0,
84  		.fendfbegin = (4 << 8) | 4,
85  		.lsynclen = 4,
86  		.lendlbegin = (60 << 8) | 10,
87  		.pixclk = 3,
88  	},
89  };
90  
91  #define DPY_W 800
92  #define DPY_H 600
93  
94  static struct fb_fix_screeninfo broadsheetfb_fix = {
95  	.id =		"broadsheetfb",
96  	.type =		FB_TYPE_PACKED_PIXELS,
97  	.visual =	FB_VISUAL_STATIC_PSEUDOCOLOR,
98  	.xpanstep =	0,
99  	.ypanstep =	0,
100  	.ywrapstep =	0,
101  	.line_length =	DPY_W,
102  	.accel =	FB_ACCEL_NONE,
103  };
104  
105  static struct fb_var_screeninfo broadsheetfb_var = {
106  	.xres		= DPY_W,
107  	.yres		= DPY_H,
108  	.xres_virtual	= DPY_W,
109  	.yres_virtual	= DPY_H,
110  	.bits_per_pixel	= 8,
111  	.grayscale	= 1,
112  	.red =		{ 0, 4, 0 },
113  	.green =	{ 0, 4, 0 },
114  	.blue =		{ 0, 4, 0 },
115  	.transp =	{ 0, 0, 0 },
116  };
117  
118  /* main broadsheetfb functions */
broadsheet_gpio_issue_data(struct broadsheetfb_par * par,u16 data)119  static void broadsheet_gpio_issue_data(struct broadsheetfb_par *par, u16 data)
120  {
121  	par->board->set_ctl(par, BS_WR, 0);
122  	par->board->set_hdb(par, data);
123  	par->board->set_ctl(par, BS_WR, 1);
124  }
125  
broadsheet_gpio_issue_cmd(struct broadsheetfb_par * par,u16 data)126  static void broadsheet_gpio_issue_cmd(struct broadsheetfb_par *par, u16 data)
127  {
128  	par->board->set_ctl(par, BS_DC, 0);
129  	broadsheet_gpio_issue_data(par, data);
130  }
131  
broadsheet_gpio_send_command(struct broadsheetfb_par * par,u16 data)132  static void broadsheet_gpio_send_command(struct broadsheetfb_par *par, u16 data)
133  {
134  	par->board->wait_for_rdy(par);
135  
136  	par->board->set_ctl(par, BS_CS, 0);
137  	broadsheet_gpio_issue_cmd(par, data);
138  	par->board->set_ctl(par, BS_DC, 1);
139  	par->board->set_ctl(par, BS_CS, 1);
140  }
141  
broadsheet_gpio_send_cmdargs(struct broadsheetfb_par * par,u16 cmd,int argc,u16 * argv)142  static void broadsheet_gpio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
143  					int argc, u16 *argv)
144  {
145  	int i;
146  
147  	par->board->wait_for_rdy(par);
148  
149  	par->board->set_ctl(par, BS_CS, 0);
150  	broadsheet_gpio_issue_cmd(par, cmd);
151  	par->board->set_ctl(par, BS_DC, 1);
152  
153  	for (i = 0; i < argc; i++)
154  		broadsheet_gpio_issue_data(par, argv[i]);
155  	par->board->set_ctl(par, BS_CS, 1);
156  }
157  
broadsheet_mmio_send_cmdargs(struct broadsheetfb_par * par,u16 cmd,int argc,u16 * argv)158  static void broadsheet_mmio_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
159  				    int argc, u16 *argv)
160  {
161  	int i;
162  
163  	par->board->mmio_write(par, BS_MMIO_CMD, cmd);
164  
165  	for (i = 0; i < argc; i++)
166  		par->board->mmio_write(par, BS_MMIO_DATA, argv[i]);
167  }
168  
broadsheet_send_command(struct broadsheetfb_par * par,u16 data)169  static void broadsheet_send_command(struct broadsheetfb_par *par, u16 data)
170  {
171  	if (par->board->mmio_write)
172  		par->board->mmio_write(par, BS_MMIO_CMD, data);
173  	else
174  		broadsheet_gpio_send_command(par, data);
175  }
176  
broadsheet_send_cmdargs(struct broadsheetfb_par * par,u16 cmd,int argc,u16 * argv)177  static void broadsheet_send_cmdargs(struct broadsheetfb_par *par, u16 cmd,
178  				    int argc, u16 *argv)
179  {
180  	if (par->board->mmio_write)
181  		broadsheet_mmio_send_cmdargs(par, cmd, argc, argv);
182  	else
183  		broadsheet_gpio_send_cmdargs(par, cmd, argc, argv);
184  }
185  
broadsheet_gpio_burst_write(struct broadsheetfb_par * par,int size,u16 * data)186  static void broadsheet_gpio_burst_write(struct broadsheetfb_par *par, int size,
187  					u16 *data)
188  {
189  	int i;
190  	u16 tmp;
191  
192  	par->board->set_ctl(par, BS_CS, 0);
193  	par->board->set_ctl(par, BS_DC, 1);
194  
195  	for (i = 0; i < size; i++) {
196  		par->board->set_ctl(par, BS_WR, 0);
197  		tmp = (data[i] & 0x0F) << 4;
198  		tmp |= (data[i] & 0x0F00) << 4;
199  		par->board->set_hdb(par, tmp);
200  		par->board->set_ctl(par, BS_WR, 1);
201  	}
202  
203  	par->board->set_ctl(par, BS_CS, 1);
204  }
205  
broadsheet_mmio_burst_write(struct broadsheetfb_par * par,int size,u16 * data)206  static void broadsheet_mmio_burst_write(struct broadsheetfb_par *par, int size,
207  				   u16 *data)
208  {
209  	int i;
210  	u16 tmp;
211  
212  	for (i = 0; i < size; i++) {
213  		tmp = (data[i] & 0x0F) << 4;
214  		tmp |= (data[i] & 0x0F00) << 4;
215  		par->board->mmio_write(par, BS_MMIO_DATA, tmp);
216  	}
217  
218  }
219  
broadsheet_burst_write(struct broadsheetfb_par * par,int size,u16 * data)220  static void broadsheet_burst_write(struct broadsheetfb_par *par, int size,
221  				   u16 *data)
222  {
223  	if (par->board->mmio_write)
224  		broadsheet_mmio_burst_write(par, size, data);
225  	else
226  		broadsheet_gpio_burst_write(par, size, data);
227  }
228  
broadsheet_gpio_get_data(struct broadsheetfb_par * par)229  static u16 broadsheet_gpio_get_data(struct broadsheetfb_par *par)
230  {
231  	u16 res;
232  	/* wait for ready to go hi. (lo is busy) */
233  	par->board->wait_for_rdy(par);
234  
235  	/* cs lo, dc lo for cmd, we lo for each data, db as usual */
236  	par->board->set_ctl(par, BS_DC, 1);
237  	par->board->set_ctl(par, BS_CS, 0);
238  	par->board->set_ctl(par, BS_WR, 0);
239  
240  	res = par->board->get_hdb(par);
241  
242  	/* strobe wr */
243  	par->board->set_ctl(par, BS_WR, 1);
244  	par->board->set_ctl(par, BS_CS, 1);
245  
246  	return res;
247  }
248  
249  
broadsheet_get_data(struct broadsheetfb_par * par)250  static u16 broadsheet_get_data(struct broadsheetfb_par *par)
251  {
252  	if (par->board->mmio_read)
253  		return par->board->mmio_read(par);
254  	else
255  		return broadsheet_gpio_get_data(par);
256  }
257  
broadsheet_gpio_write_reg(struct broadsheetfb_par * par,u16 reg,u16 data)258  static void broadsheet_gpio_write_reg(struct broadsheetfb_par *par, u16 reg,
259  					u16 data)
260  {
261  	/* wait for ready to go hi. (lo is busy) */
262  	par->board->wait_for_rdy(par);
263  
264  	/* cs lo, dc lo for cmd, we lo for each data, db as usual */
265  	par->board->set_ctl(par, BS_CS, 0);
266  
267  	broadsheet_gpio_issue_cmd(par, BS_CMD_WR_REG);
268  
269  	par->board->set_ctl(par, BS_DC, 1);
270  
271  	broadsheet_gpio_issue_data(par, reg);
272  	broadsheet_gpio_issue_data(par, data);
273  
274  	par->board->set_ctl(par, BS_CS, 1);
275  }
276  
broadsheet_mmio_write_reg(struct broadsheetfb_par * par,u16 reg,u16 data)277  static void broadsheet_mmio_write_reg(struct broadsheetfb_par *par, u16 reg,
278  				 u16 data)
279  {
280  	par->board->mmio_write(par, BS_MMIO_CMD, BS_CMD_WR_REG);
281  	par->board->mmio_write(par, BS_MMIO_DATA, reg);
282  	par->board->mmio_write(par, BS_MMIO_DATA, data);
283  
284  }
285  
broadsheet_write_reg(struct broadsheetfb_par * par,u16 reg,u16 data)286  static void broadsheet_write_reg(struct broadsheetfb_par *par, u16 reg,
287  					u16 data)
288  {
289  	if (par->board->mmio_write)
290  		broadsheet_mmio_write_reg(par, reg, data);
291  	else
292  		broadsheet_gpio_write_reg(par, reg, data);
293  }
294  
broadsheet_write_reg32(struct broadsheetfb_par * par,u16 reg,u32 data)295  static void broadsheet_write_reg32(struct broadsheetfb_par *par, u16 reg,
296  					u32 data)
297  {
298  	broadsheet_write_reg(par, reg, cpu_to_le32(data) & 0xFFFF);
299  	broadsheet_write_reg(par, reg + 2, (cpu_to_le32(data) >> 16) & 0xFFFF);
300  }
301  
302  
broadsheet_read_reg(struct broadsheetfb_par * par,u16 reg)303  static u16 broadsheet_read_reg(struct broadsheetfb_par *par, u16 reg)
304  {
305  	broadsheet_send_cmdargs(par, BS_CMD_RD_REG, 1, &reg);
306  	par->board->wait_for_rdy(par);
307  	return broadsheet_get_data(par);
308  }
309  
310  /* functions for waveform manipulation */
is_broadsheet_pll_locked(struct broadsheetfb_par * par)311  static int is_broadsheet_pll_locked(struct broadsheetfb_par *par)
312  {
313  	return broadsheet_read_reg(par, 0x000A) & 0x0001;
314  }
315  
broadsheet_setup_plls(struct broadsheetfb_par * par)316  static int broadsheet_setup_plls(struct broadsheetfb_par *par)
317  {
318  	int retry_count = 0;
319  	u16 tmp;
320  
321  	/* disable arral saemipu mode */
322  	broadsheet_write_reg(par, 0x0006, 0x0000);
323  
324  	broadsheet_write_reg(par, 0x0010, 0x0004);
325  	broadsheet_write_reg(par, 0x0012, 0x5949);
326  	broadsheet_write_reg(par, 0x0014, 0x0040);
327  	broadsheet_write_reg(par, 0x0016, 0x0000);
328  
329  	do {
330  		if (retry_count++ > 100)
331  			return -ETIMEDOUT;
332  		mdelay(1);
333  	} while (!is_broadsheet_pll_locked(par));
334  
335  	tmp = broadsheet_read_reg(par, 0x0006);
336  	tmp &= ~0x1;
337  	broadsheet_write_reg(par, 0x0006, tmp);
338  
339  	return 0;
340  }
341  
broadsheet_setup_spi(struct broadsheetfb_par * par)342  static int broadsheet_setup_spi(struct broadsheetfb_par *par)
343  {
344  
345  	broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
346  	broadsheet_write_reg(par, 0x0208, 0x0001);
347  
348  	return 0;
349  }
350  
broadsheet_setup_spiflash(struct broadsheetfb_par * par,u16 * orig_sfmcd)351  static int broadsheet_setup_spiflash(struct broadsheetfb_par *par,
352  						u16 *orig_sfmcd)
353  {
354  
355  	*orig_sfmcd = broadsheet_read_reg(par, 0x0204);
356  	broadsheet_write_reg(par, 0x0208, 0);
357  	broadsheet_write_reg(par, 0x0204, 0);
358  	broadsheet_write_reg(par, 0x0204, ((3 << 3) | 1));
359  
360  	return 0;
361  }
362  
broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par * par,u16 reg,int bitnum,int val,int timeout)363  static int broadsheet_spiflash_wait_for_bit(struct broadsheetfb_par *par,
364  						u16 reg, int bitnum, int val,
365  						int timeout)
366  {
367  	u16 tmp;
368  
369  	do {
370  		tmp = broadsheet_read_reg(par, reg);
371  		if (((tmp >> bitnum) & 1) == val)
372  			return 0;
373  		mdelay(1);
374  	} while (timeout--);
375  
376  	return -ETIMEDOUT;
377  }
378  
broadsheet_spiflash_write_byte(struct broadsheetfb_par * par,u8 data)379  static int broadsheet_spiflash_write_byte(struct broadsheetfb_par *par, u8 data)
380  {
381  	broadsheet_write_reg(par, 0x0202, (data | 0x100));
382  
383  	return broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
384  }
385  
broadsheet_spiflash_read_byte(struct broadsheetfb_par * par,u8 * data)386  static int broadsheet_spiflash_read_byte(struct broadsheetfb_par *par, u8 *data)
387  {
388  	int err;
389  	u16 tmp;
390  
391  	broadsheet_write_reg(par, 0x0202, 0);
392  
393  	err = broadsheet_spiflash_wait_for_bit(par, 0x0206, 3, 0, 100);
394  	if (err)
395  		return err;
396  
397  	tmp = broadsheet_read_reg(par, 0x200);
398  
399  	*data = tmp & 0xFF;
400  
401  	return 0;
402  }
403  
broadsheet_spiflash_wait_for_status(struct broadsheetfb_par * par,int timeout)404  static int broadsheet_spiflash_wait_for_status(struct broadsheetfb_par *par,
405  								int timeout)
406  {
407  	u8 tmp;
408  	int err;
409  
410  	do {
411  		broadsheet_write_reg(par, 0x0208, 1);
412  
413  		err = broadsheet_spiflash_write_byte(par, 0x05);
414  		if (err)
415  			goto failout;
416  
417  		err = broadsheet_spiflash_read_byte(par, &tmp);
418  		if (err)
419  			goto failout;
420  
421  		broadsheet_write_reg(par, 0x0208, 0);
422  
423  		if (!(tmp & 0x1))
424  			return 0;
425  
426  		mdelay(5);
427  	} while (timeout--);
428  
429  	dev_err(par->info->device, "Timed out waiting for spiflash status\n");
430  	return -ETIMEDOUT;
431  
432  failout:
433  	broadsheet_write_reg(par, 0x0208, 0);
434  	return err;
435  }
436  
broadsheet_spiflash_op_on_address(struct broadsheetfb_par * par,u8 op,u32 addr)437  static int broadsheet_spiflash_op_on_address(struct broadsheetfb_par *par,
438  							u8 op, u32 addr)
439  {
440  	int i;
441  	u8 tmp;
442  	int err;
443  
444  	broadsheet_write_reg(par, 0x0208, 1);
445  
446  	err = broadsheet_spiflash_write_byte(par, op);
447  	if (err)
448  		return err;
449  
450  	for (i = 2; i >= 0; i--) {
451  		tmp = ((addr >> (i * 8)) & 0xFF);
452  		err = broadsheet_spiflash_write_byte(par, tmp);
453  		if (err)
454  			return err;
455  	}
456  
457  	return err;
458  }
459  
broadsheet_verify_spiflash(struct broadsheetfb_par * par,int * flash_type)460  static int broadsheet_verify_spiflash(struct broadsheetfb_par *par,
461  						int *flash_type)
462  {
463  	int err = 0;
464  	u8 sig;
465  
466  	err = broadsheet_spiflash_op_on_address(par, 0xAB, 0x00000000);
467  	if (err)
468  		goto failout;
469  
470  	err = broadsheet_spiflash_read_byte(par, &sig);
471  	if (err)
472  		goto failout;
473  
474  	if ((sig != 0x10) && (sig != 0x11)) {
475  		dev_err(par->info->device, "Unexpected flash type\n");
476  		err = -EINVAL;
477  		goto failout;
478  	}
479  
480  	*flash_type = sig;
481  
482  failout:
483  	broadsheet_write_reg(par, 0x0208, 0);
484  	return err;
485  }
486  
broadsheet_setup_for_wfm_write(struct broadsheetfb_par * par,u16 * initial_sfmcd,int * flash_type)487  static int broadsheet_setup_for_wfm_write(struct broadsheetfb_par *par,
488  					u16 *initial_sfmcd, int *flash_type)
489  
490  {
491  	int err;
492  
493  	err = broadsheet_setup_plls(par);
494  	if (err)
495  		return err;
496  
497  	broadsheet_write_reg(par, 0x0106, 0x0203);
498  
499  	err = broadsheet_setup_spi(par);
500  	if (err)
501  		return err;
502  
503  	err = broadsheet_setup_spiflash(par, initial_sfmcd);
504  	if (err)
505  		return err;
506  
507  	return broadsheet_verify_spiflash(par, flash_type);
508  }
509  
broadsheet_spiflash_write_control(struct broadsheetfb_par * par,int mode)510  static int broadsheet_spiflash_write_control(struct broadsheetfb_par *par,
511  						int mode)
512  {
513  	int err;
514  
515  	broadsheet_write_reg(par, 0x0208, 1);
516  	if (mode)
517  		err = broadsheet_spiflash_write_byte(par, 0x06);
518  	else
519  		err = broadsheet_spiflash_write_byte(par, 0x04);
520  
521  	broadsheet_write_reg(par, 0x0208, 0);
522  	return err;
523  }
524  
broadsheet_spiflash_erase_sector(struct broadsheetfb_par * par,int addr)525  static int broadsheet_spiflash_erase_sector(struct broadsheetfb_par *par,
526  						int addr)
527  {
528  	int err;
529  
530  	broadsheet_spiflash_write_control(par, 1);
531  
532  	err = broadsheet_spiflash_op_on_address(par, 0xD8, addr);
533  
534  	broadsheet_write_reg(par, 0x0208, 0);
535  
536  	if (err)
537  		return err;
538  
539  	err = broadsheet_spiflash_wait_for_status(par, 1000);
540  
541  	return err;
542  }
543  
broadsheet_spiflash_read_range(struct broadsheetfb_par * par,int addr,int size,char * data)544  static int broadsheet_spiflash_read_range(struct broadsheetfb_par *par,
545  						int addr, int size, char *data)
546  {
547  	int err;
548  	int i;
549  
550  	err = broadsheet_spiflash_op_on_address(par, 0x03, addr);
551  	if (err)
552  		goto failout;
553  
554  	for (i = 0; i < size; i++) {
555  		err = broadsheet_spiflash_read_byte(par, &data[i]);
556  		if (err)
557  			goto failout;
558  	}
559  
560  failout:
561  	broadsheet_write_reg(par, 0x0208, 0);
562  	return err;
563  }
564  
565  #define BS_SPIFLASH_PAGE_SIZE 256
broadsheet_spiflash_write_page(struct broadsheetfb_par * par,int addr,const char * data)566  static int broadsheet_spiflash_write_page(struct broadsheetfb_par *par,
567  						int addr, const char *data)
568  {
569  	int err;
570  	int i;
571  
572  	broadsheet_spiflash_write_control(par, 1);
573  
574  	err = broadsheet_spiflash_op_on_address(par, 0x02, addr);
575  	if (err)
576  		goto failout;
577  
578  	for (i = 0; i < BS_SPIFLASH_PAGE_SIZE; i++) {
579  		err = broadsheet_spiflash_write_byte(par, data[i]);
580  		if (err)
581  			goto failout;
582  	}
583  
584  	broadsheet_write_reg(par, 0x0208, 0);
585  
586  	err = broadsheet_spiflash_wait_for_status(par, 100);
587  
588  failout:
589  	return err;
590  }
591  
broadsheet_spiflash_write_sector(struct broadsheetfb_par * par,int addr,const char * data,int sector_size)592  static int broadsheet_spiflash_write_sector(struct broadsheetfb_par *par,
593  				int addr, const char *data, int sector_size)
594  {
595  	int i;
596  	int err;
597  
598  	for (i = 0; i < sector_size; i += BS_SPIFLASH_PAGE_SIZE) {
599  		err = broadsheet_spiflash_write_page(par, addr + i, &data[i]);
600  		if (err)
601  			return err;
602  	}
603  	return 0;
604  }
605  
606  /*
607   * The caller must guarantee that the data to be rewritten is entirely
608   * contained within this sector. That is, data_start_addr + data_len
609   * must be less than sector_start_addr + sector_size.
610   */
broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par * par,int sector_size,int data_start_addr,int data_len,const char * data)611  static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
612  					int sector_size, int data_start_addr,
613  					int data_len, const char *data)
614  {
615  	int err;
616  	char *sector_buffer;
617  	int tail_start_addr;
618  	int start_sector_addr;
619  
620  	sector_buffer = kzalloc(sector_size, GFP_KERNEL);
621  	if (!sector_buffer)
622  		return -ENOMEM;
623  
624  	/* the start address of the sector is the 0th byte of that sector */
625  	start_sector_addr = (data_start_addr / sector_size) * sector_size;
626  
627  	/*
628  	 * check if there is head data that we need to readback into our sector
629  	 * buffer first
630  	 */
631  	if (data_start_addr != start_sector_addr) {
632  		/*
633  		 * we need to read every byte up till the start address of our
634  		 * data and we put it into our sector buffer.
635  		 */
636  		err = broadsheet_spiflash_read_range(par, start_sector_addr,
637  						data_start_addr, sector_buffer);
638  		if (err)
639  			goto out;
640  	}
641  
642  	/* now we copy our data into the right place in the sector buffer */
643  	memcpy(sector_buffer + data_start_addr, data, data_len);
644  
645  	/*
646  	 * now we check if there is a tail section of the sector that we need to
647  	 * readback.
648  	 */
649  	tail_start_addr = (data_start_addr + data_len) % sector_size;
650  
651  	if (tail_start_addr) {
652  		int tail_len;
653  
654  		tail_len = sector_size - tail_start_addr;
655  
656  		/* now we read this tail into our sector buffer */
657  		err = broadsheet_spiflash_read_range(par, tail_start_addr,
658  			tail_len, sector_buffer + tail_start_addr);
659  		if (err)
660  			goto out;
661  	}
662  
663  	/* if we got here we have the full sector that we want to rewrite. */
664  
665  	/* first erase the sector */
666  	err = broadsheet_spiflash_erase_sector(par, start_sector_addr);
667  	if (err)
668  		goto out;
669  
670  	/* now write it */
671  	err = broadsheet_spiflash_write_sector(par, start_sector_addr,
672  					sector_buffer, sector_size);
673  out:
674  	kfree(sector_buffer);
675  	return err;
676  }
677  
broadsheet_write_spiflash(struct broadsheetfb_par * par,u32 wfm_addr,const u8 * wfm,int bytecount,int flash_type)678  static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
679  				const u8 *wfm, int bytecount, int flash_type)
680  {
681  	int sector_size;
682  	int err;
683  	int cur_addr;
684  	int writecount;
685  	int maxlen;
686  	int offset = 0;
687  
688  	switch (flash_type) {
689  	case 0x10:
690  		sector_size = 32*1024;
691  		break;
692  	case 0x11:
693  	default:
694  		sector_size = 64*1024;
695  		break;
696  	}
697  
698  	while (bytecount) {
699  		cur_addr = wfm_addr + offset;
700  		maxlen = roundup(cur_addr, sector_size) - cur_addr;
701  		writecount = min(bytecount, maxlen);
702  
703  		err = broadsheet_spiflash_rewrite_sector(par, sector_size,
704  				cur_addr, writecount, wfm + offset);
705  		if (err)
706  			return err;
707  
708  		offset += writecount;
709  		bytecount -= writecount;
710  	}
711  
712  	return 0;
713  }
714  
broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par * par,const u8 * wfm,size_t wfm_size)715  static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
716  						const u8 *wfm, size_t wfm_size)
717  {
718  	int err = 0;
719  	u16 initial_sfmcd = 0;
720  	int flash_type = 0;
721  
722  	err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
723  	if (err)
724  		goto failout;
725  
726  	err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
727  
728  failout:
729  	broadsheet_write_reg(par, 0x0204, initial_sfmcd);
730  	return err;
731  }
732  
broadsheet_loadstore_waveform(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)733  static ssize_t broadsheet_loadstore_waveform(struct device *dev,
734  						struct device_attribute *attr,
735  						const char *buf, size_t len)
736  {
737  	int err;
738  	struct fb_info *info = dev_get_drvdata(dev);
739  	struct broadsheetfb_par *par = info->par;
740  	const struct firmware *fw_entry;
741  
742  	if (len < 1)
743  		return -EINVAL;
744  
745  	err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
746  	if (err < 0) {
747  		dev_err(dev, "Failed to get broadsheet waveform\n");
748  		goto err_failed;
749  	}
750  
751  	/* try to enforce reasonable min max on waveform */
752  	if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
753  		dev_err(dev, "Invalid waveform\n");
754  		err = -EINVAL;
755  		goto err_fw;
756  	}
757  
758  	mutex_lock(&(par->io_lock));
759  	err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
760  							fw_entry->size);
761  
762  	mutex_unlock(&(par->io_lock));
763  	if (err < 0) {
764  		dev_err(dev, "Failed to store broadsheet waveform\n");
765  		goto err_fw;
766  	}
767  
768  	dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
769  
770  	err = len;
771  
772  err_fw:
773  	release_firmware(fw_entry);
774  err_failed:
775  	return err;
776  }
777  static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
778  			broadsheet_loadstore_waveform);
779  
780  /* upper level functions that manipulate the display and other stuff */
broadsheet_init_display(struct broadsheetfb_par * par)781  static void broadsheet_init_display(struct broadsheetfb_par *par)
782  {
783  	u16 args[5];
784  	int xres = par->info->var.xres;
785  	int yres = par->info->var.yres;
786  
787  	args[0] = panel_table[par->panel_index].w;
788  	args[1] = panel_table[par->panel_index].h;
789  	args[2] = panel_table[par->panel_index].sdcfg;
790  	args[3] = panel_table[par->panel_index].gdcfg;
791  	args[4] = panel_table[par->panel_index].lutfmt;
792  	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
793  
794  	/* did the controller really set it? */
795  	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
796  
797  	args[0] = panel_table[par->panel_index].fsynclen;
798  	args[1] = panel_table[par->panel_index].fendfbegin;
799  	args[2] = panel_table[par->panel_index].lsynclen;
800  	args[3] = panel_table[par->panel_index].lendlbegin;
801  	args[4] = panel_table[par->panel_index].pixclk;
802  	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
803  
804  	broadsheet_write_reg32(par, 0x310, xres*yres*2);
805  
806  	/* setup waveform */
807  	args[0] = 0x886;
808  	args[1] = 0;
809  	broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args);
810  
811  	broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR);
812  
813  	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
814  
815  	broadsheet_write_reg(par, 0x330, 0x84);
816  
817  	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
818  
819  	args[0] = (0x3 << 4);
820  	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
821  
822  	args[0] = 0x154;
823  	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
824  
825  	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
826  					panel_table[par->panel_index].h)/2,
827  					(u16 *)par->info->screen_buffer);
828  
829  	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
830  
831  	args[0] = 0x4300;
832  	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
833  
834  	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
835  
836  	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
837  
838  	par->board->wait_for_rdy(par);
839  }
840  
broadsheet_identify(struct broadsheetfb_par * par)841  static void broadsheet_identify(struct broadsheetfb_par *par)
842  {
843  	u16 rev, prc;
844  	struct device *dev = par->info->device;
845  
846  	rev = broadsheet_read_reg(par, BS_REG_REV);
847  	prc = broadsheet_read_reg(par, BS_REG_PRC);
848  	dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
849  
850  	if (prc != 0x0047)
851  		dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
852  	if (rev != 0x0100)
853  		dev_warn(dev, "Unrecognized Broadsheet Revision\n");
854  }
855  
broadsheet_init(struct broadsheetfb_par * par)856  static void broadsheet_init(struct broadsheetfb_par *par)
857  {
858  	broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
859  	/* the controller needs a second */
860  	msleep(1000);
861  	broadsheet_init_display(par);
862  }
863  
broadsheetfb_dpy_update_pages(struct broadsheetfb_par * par,u16 y1,u16 y2)864  static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
865  						u16 y1, u16 y2)
866  {
867  	u16 args[5];
868  	unsigned char *buf = par->info->screen_buffer;
869  
870  	mutex_lock(&(par->io_lock));
871  	/* y1 must be a multiple of 4 so drop the lower bits */
872  	y1 &= 0xFFFC;
873  	/* y2 must be a multiple of 4 , but - 1 so up the lower bits */
874  	y2 |= 0x0003;
875  
876  	args[0] = 0x3 << 4;
877  	args[1] = 0;
878  	args[2] = y1;
879  	args[3] = cpu_to_le16(par->info->var.xres);
880  	args[4] = y2;
881  	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args);
882  
883  	args[0] = 0x154;
884  	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
885  
886  	buf += y1 * par->info->var.xres;
887  	broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2,
888  				(u16 *) buf);
889  
890  	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
891  
892  	args[0] = 0x4300;
893  	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
894  
895  	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
896  
897  	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
898  
899  	par->board->wait_for_rdy(par);
900  	mutex_unlock(&(par->io_lock));
901  
902  }
903  
broadsheetfb_dpy_update(struct broadsheetfb_par * par)904  static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
905  {
906  	u16 args[5];
907  
908  	mutex_lock(&(par->io_lock));
909  	args[0] = 0x3 << 4;
910  	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
911  
912  	args[0] = 0x154;
913  	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
914  	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
915  					panel_table[par->panel_index].h)/2,
916  					(u16 *)par->info->screen_buffer);
917  
918  	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
919  
920  	args[0] = 0x4300;
921  	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
922  
923  	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
924  
925  	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
926  
927  	par->board->wait_for_rdy(par);
928  	mutex_unlock(&(par->io_lock));
929  }
930  
931  /* this is called back from the deferred io workqueue */
broadsheetfb_dpy_deferred_io(struct fb_info * info,struct list_head * pagereflist)932  static void broadsheetfb_dpy_deferred_io(struct fb_info *info, struct list_head *pagereflist)
933  {
934  	u16 y1 = 0, h = 0;
935  	unsigned long prev_offset = ULONG_MAX;
936  	struct fb_deferred_io_pageref *pageref;
937  	int h_inc;
938  	u16 yres = info->var.yres;
939  	u16 xres = info->var.xres;
940  
941  	/* height increment is fixed per page */
942  	h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
943  
944  	/* walk the written page list and swizzle the data */
945  	list_for_each_entry(pageref, pagereflist, list) {
946  		if (prev_offset == ULONG_MAX) {
947  			/* just starting so assign first page */
948  			y1 = pageref->offset / xres;
949  			h = h_inc;
950  		} else if ((prev_offset + PAGE_SIZE) == pageref->offset) {
951  			/* this page is consecutive so increase our height */
952  			h += h_inc;
953  		} else {
954  			/* page not consecutive, issue previous update first */
955  			broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
956  			/* start over with our non consecutive page */
957  			y1 = pageref->offset / xres;
958  			h = h_inc;
959  		}
960  		prev_offset = pageref->offset;
961  	}
962  
963  	/* if we still have any pages to update we do so now */
964  	if (h >= yres) {
965  		/* its a full screen update, just do it */
966  		broadsheetfb_dpy_update(info->par);
967  	} else {
968  		broadsheetfb_dpy_update_pages(info->par, y1,
969  						min((u16) (y1 + h), yres));
970  	}
971  }
972  
broadsheetfb_defio_damage_range(struct fb_info * info,off_t off,size_t len)973  static void broadsheetfb_defio_damage_range(struct fb_info *info, off_t off, size_t len)
974  {
975  	struct broadsheetfb_par *par = info->par;
976  
977  	broadsheetfb_dpy_update(par);
978  }
979  
broadsheetfb_defio_damage_area(struct fb_info * info,u32 x,u32 y,u32 width,u32 height)980  static void broadsheetfb_defio_damage_area(struct fb_info *info, u32 x, u32 y,
981  					   u32 width, u32 height)
982  {
983  	struct broadsheetfb_par *par = info->par;
984  
985  	broadsheetfb_dpy_update(par);
986  }
987  
988  FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(broadsheetfb,
989  				   broadsheetfb_defio_damage_range,
990  				   broadsheetfb_defio_damage_area)
991  
992  static const struct fb_ops broadsheetfb_ops = {
993  	.owner	= THIS_MODULE,
994  	FB_DEFAULT_DEFERRED_OPS(broadsheetfb),
995  };
996  
997  static struct fb_deferred_io broadsheetfb_defio = {
998  	.delay			= HZ/4,
999  	.sort_pagereflist	= true,
1000  	.deferred_io		= broadsheetfb_dpy_deferred_io,
1001  };
1002  
broadsheetfb_probe(struct platform_device * dev)1003  static int broadsheetfb_probe(struct platform_device *dev)
1004  {
1005  	struct fb_info *info;
1006  	struct broadsheet_board *board;
1007  	int retval = -ENOMEM;
1008  	int videomemorysize;
1009  	unsigned char *videomemory;
1010  	struct broadsheetfb_par *par;
1011  	int i;
1012  	int dpyw, dpyh;
1013  	int panel_index;
1014  
1015  	/* pick up board specific routines */
1016  	board = dev->dev.platform_data;
1017  	if (!board)
1018  		return -EINVAL;
1019  
1020  	/* try to count device specific driver, if can't, platform recalls */
1021  	if (!try_module_get(board->owner))
1022  		return -ENODEV;
1023  
1024  	info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
1025  	if (!info)
1026  		goto err;
1027  
1028  	switch (board->get_panel_type()) {
1029  	case 37:
1030  		panel_index = 1;
1031  		break;
1032  	case 97:
1033  		panel_index = 2;
1034  		break;
1035  	case 6:
1036  	default:
1037  		panel_index = 0;
1038  		break;
1039  	}
1040  
1041  	dpyw = panel_table[panel_index].w;
1042  	dpyh = panel_table[panel_index].h;
1043  
1044  	videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
1045  
1046  	videomemory = vzalloc(videomemorysize);
1047  	if (!videomemory)
1048  		goto err_fb_rel;
1049  
1050  	info->screen_buffer = videomemory;
1051  	info->fbops = &broadsheetfb_ops;
1052  
1053  	broadsheetfb_var.xres = dpyw;
1054  	broadsheetfb_var.yres = dpyh;
1055  	broadsheetfb_var.xres_virtual = dpyw;
1056  	broadsheetfb_var.yres_virtual = dpyh;
1057  	info->var = broadsheetfb_var;
1058  
1059  	broadsheetfb_fix.line_length = dpyw;
1060  	info->fix = broadsheetfb_fix;
1061  	info->fix.smem_len = videomemorysize;
1062  	par = info->par;
1063  	par->panel_index = panel_index;
1064  	par->info = info;
1065  	par->board = board;
1066  	par->write_reg = broadsheet_write_reg;
1067  	par->read_reg = broadsheet_read_reg;
1068  	init_waitqueue_head(&par->waitq);
1069  
1070  	mutex_init(&par->io_lock);
1071  
1072  	info->flags = FBINFO_VIRTFB;
1073  
1074  	info->fbdefio = &broadsheetfb_defio;
1075  	fb_deferred_io_init(info);
1076  
1077  	retval = fb_alloc_cmap(&info->cmap, 16, 0);
1078  	if (retval < 0) {
1079  		dev_err(&dev->dev, "Failed to allocate colormap\n");
1080  		goto err_vfree;
1081  	}
1082  
1083  	/* set cmap */
1084  	for (i = 0; i < 16; i++)
1085  		info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
1086  	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
1087  	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
1088  
1089  	retval = par->board->setup_irq(info);
1090  	if (retval < 0)
1091  		goto err_cmap;
1092  
1093  	/* this inits the dpy */
1094  	retval = board->init(par);
1095  	if (retval < 0)
1096  		goto err_free_irq;
1097  
1098  	broadsheet_identify(par);
1099  
1100  	broadsheet_init(par);
1101  
1102  	retval = register_framebuffer(info);
1103  	if (retval < 0)
1104  		goto err_free_irq;
1105  
1106  	platform_set_drvdata(dev, info);
1107  
1108  	retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1109  	if (retval < 0)
1110  		goto err_unreg_fb;
1111  
1112  	fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n",
1113  		videomemorysize >> 10);
1114  
1115  
1116  	return 0;
1117  
1118  err_unreg_fb:
1119  	unregister_framebuffer(info);
1120  err_free_irq:
1121  	board->cleanup(par);
1122  err_cmap:
1123  	fb_dealloc_cmap(&info->cmap);
1124  err_vfree:
1125  	vfree(videomemory);
1126  err_fb_rel:
1127  	framebuffer_release(info);
1128  err:
1129  	module_put(board->owner);
1130  	return retval;
1131  
1132  }
1133  
broadsheetfb_remove(struct platform_device * dev)1134  static void broadsheetfb_remove(struct platform_device *dev)
1135  {
1136  	struct fb_info *info = platform_get_drvdata(dev);
1137  
1138  	if (info) {
1139  		struct broadsheetfb_par *par = info->par;
1140  
1141  		device_remove_file(info->device, &dev_attr_loadstore_waveform);
1142  		unregister_framebuffer(info);
1143  		fb_deferred_io_cleanup(info);
1144  		par->board->cleanup(par);
1145  		fb_dealloc_cmap(&info->cmap);
1146  		vfree(info->screen_buffer);
1147  		module_put(par->board->owner);
1148  		framebuffer_release(info);
1149  	}
1150  }
1151  
1152  static struct platform_driver broadsheetfb_driver = {
1153  	.probe	= broadsheetfb_probe,
1154  	.remove_new = broadsheetfb_remove,
1155  	.driver	= {
1156  		.name	= "broadsheetfb",
1157  	},
1158  };
1159  module_platform_driver(broadsheetfb_driver);
1160  
1161  MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
1162  MODULE_AUTHOR("Jaya Kumar");
1163  MODULE_LICENSE("GPL");
1164  
1165  MODULE_FIRMWARE("broadsheet.wbf");
1166