• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(sizeof(char)*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 			return err;
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 			return err;
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 		return err;
669 
670 	/* now write it */
671 	err = broadsheet_spiflash_write_sector(par, start_sector_addr,
672 					sector_buffer, sector_size);
673 	return err;
674 }
675 
broadsheet_write_spiflash(struct broadsheetfb_par * par,u32 wfm_addr,const u8 * wfm,int bytecount,int flash_type)676 static int broadsheet_write_spiflash(struct broadsheetfb_par *par, u32 wfm_addr,
677 				const u8 *wfm, int bytecount, int flash_type)
678 {
679 	int sector_size;
680 	int err;
681 	int cur_addr;
682 	int writecount;
683 	int maxlen;
684 	int offset = 0;
685 
686 	switch (flash_type) {
687 	case 0x10:
688 		sector_size = 32*1024;
689 		break;
690 	case 0x11:
691 	default:
692 		sector_size = 64*1024;
693 		break;
694 	}
695 
696 	while (bytecount) {
697 		cur_addr = wfm_addr + offset;
698 		maxlen = roundup(cur_addr, sector_size) - cur_addr;
699 		writecount = min(bytecount, maxlen);
700 
701 		err = broadsheet_spiflash_rewrite_sector(par, sector_size,
702 				cur_addr, writecount, wfm + offset);
703 		if (err)
704 			return err;
705 
706 		offset += writecount;
707 		bytecount -= writecount;
708 	}
709 
710 	return 0;
711 }
712 
broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par * par,const u8 * wfm,size_t wfm_size)713 static int broadsheet_store_waveform_to_spiflash(struct broadsheetfb_par *par,
714 						const u8 *wfm, size_t wfm_size)
715 {
716 	int err = 0;
717 	u16 initial_sfmcd = 0;
718 	int flash_type = 0;
719 
720 	err = broadsheet_setup_for_wfm_write(par, &initial_sfmcd, &flash_type);
721 	if (err)
722 		goto failout;
723 
724 	err = broadsheet_write_spiflash(par, 0x886, wfm, wfm_size, flash_type);
725 
726 failout:
727 	broadsheet_write_reg(par, 0x0204, initial_sfmcd);
728 	return err;
729 }
730 
broadsheet_loadstore_waveform(struct device * dev,struct device_attribute * attr,const char * buf,size_t len)731 static ssize_t broadsheet_loadstore_waveform(struct device *dev,
732 						struct device_attribute *attr,
733 						const char *buf, size_t len)
734 {
735 	int err;
736 	struct fb_info *info = dev_get_drvdata(dev);
737 	struct broadsheetfb_par *par = info->par;
738 	const struct firmware *fw_entry;
739 
740 	if (len < 1)
741 		return -EINVAL;
742 
743 	err = request_firmware(&fw_entry, "broadsheet.wbf", dev);
744 	if (err < 0) {
745 		dev_err(dev, "Failed to get broadsheet waveform\n");
746 		goto err_failed;
747 	}
748 
749 	/* try to enforce reasonable min max on waveform */
750 	if ((fw_entry->size < 8*1024) || (fw_entry->size > 64*1024)) {
751 		dev_err(dev, "Invalid waveform\n");
752 		err = -EINVAL;
753 		goto err_failed;
754 	}
755 
756 	mutex_lock(&(par->io_lock));
757 	err = broadsheet_store_waveform_to_spiflash(par, fw_entry->data,
758 							fw_entry->size);
759 
760 	mutex_unlock(&(par->io_lock));
761 	if (err < 0) {
762 		dev_err(dev, "Failed to store broadsheet waveform\n");
763 		goto err_failed;
764 	}
765 
766 	dev_info(dev, "Stored broadsheet waveform, size %zd\n", fw_entry->size);
767 
768 	return len;
769 
770 err_failed:
771 	return err;
772 }
773 static DEVICE_ATTR(loadstore_waveform, S_IWUSR, NULL,
774 			broadsheet_loadstore_waveform);
775 
776 /* upper level functions that manipulate the display and other stuff */
broadsheet_init_display(struct broadsheetfb_par * par)777 static void broadsheet_init_display(struct broadsheetfb_par *par)
778 {
779 	u16 args[5];
780 	int xres = par->info->var.xres;
781 	int yres = par->info->var.yres;
782 
783 	args[0] = panel_table[par->panel_index].w;
784 	args[1] = panel_table[par->panel_index].h;
785 	args[2] = panel_table[par->panel_index].sdcfg;
786 	args[3] = panel_table[par->panel_index].gdcfg;
787 	args[4] = panel_table[par->panel_index].lutfmt;
788 	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
789 
790 	/* did the controller really set it? */
791 	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_CFG, 5, args);
792 
793 	args[0] = panel_table[par->panel_index].fsynclen;
794 	args[1] = panel_table[par->panel_index].fendfbegin;
795 	args[2] = panel_table[par->panel_index].lsynclen;
796 	args[3] = panel_table[par->panel_index].lendlbegin;
797 	args[4] = panel_table[par->panel_index].pixclk;
798 	broadsheet_send_cmdargs(par, BS_CMD_INIT_DSPE_TMG, 5, args);
799 
800 	broadsheet_write_reg32(par, 0x310, xres*yres*2);
801 
802 	/* setup waveform */
803 	args[0] = 0x886;
804 	args[1] = 0;
805 	broadsheet_send_cmdargs(par, BS_CMD_RD_WFM_INFO, 2, args);
806 
807 	broadsheet_send_command(par, BS_CMD_UPD_GDRV_CLR);
808 
809 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
810 
811 	broadsheet_write_reg(par, 0x330, 0x84);
812 
813 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
814 
815 	args[0] = (0x3 << 4);
816 	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
817 
818 	args[0] = 0x154;
819 	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
820 
821 	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
822 					panel_table[par->panel_index].h)/2,
823 					(u16 *) par->info->screen_base);
824 
825 	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
826 
827 	args[0] = 0x4300;
828 	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
829 
830 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
831 
832 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
833 
834 	par->board->wait_for_rdy(par);
835 }
836 
broadsheet_identify(struct broadsheetfb_par * par)837 static void broadsheet_identify(struct broadsheetfb_par *par)
838 {
839 	u16 rev, prc;
840 	struct device *dev = par->info->device;
841 
842 	rev = broadsheet_read_reg(par, BS_REG_REV);
843 	prc = broadsheet_read_reg(par, BS_REG_PRC);
844 	dev_info(dev, "Broadsheet Rev 0x%x, Product Code 0x%x\n", rev, prc);
845 
846 	if (prc != 0x0047)
847 		dev_warn(dev, "Unrecognized Broadsheet Product Code\n");
848 	if (rev != 0x0100)
849 		dev_warn(dev, "Unrecognized Broadsheet Revision\n");
850 }
851 
broadsheet_init(struct broadsheetfb_par * par)852 static void broadsheet_init(struct broadsheetfb_par *par)
853 {
854 	broadsheet_send_command(par, BS_CMD_INIT_SYS_RUN);
855 	/* the controller needs a second */
856 	msleep(1000);
857 	broadsheet_init_display(par);
858 }
859 
broadsheetfb_dpy_update_pages(struct broadsheetfb_par * par,u16 y1,u16 y2)860 static void broadsheetfb_dpy_update_pages(struct broadsheetfb_par *par,
861 						u16 y1, u16 y2)
862 {
863 	u16 args[5];
864 	unsigned char *buf = (unsigned char *)par->info->screen_base;
865 
866 	mutex_lock(&(par->io_lock));
867 	/* y1 must be a multiple of 4 so drop the lower bits */
868 	y1 &= 0xFFFC;
869 	/* y2 must be a multiple of 4 , but - 1 so up the lower bits */
870 	y2 |= 0x0003;
871 
872 	args[0] = 0x3 << 4;
873 	args[1] = 0;
874 	args[2] = y1;
875 	args[3] = cpu_to_le16(par->info->var.xres);
876 	args[4] = y2;
877 	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG_AREA, 5, args);
878 
879 	args[0] = 0x154;
880 	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
881 
882 	buf += y1 * par->info->var.xres;
883 	broadsheet_burst_write(par, ((1 + y2 - y1) * par->info->var.xres)/2,
884 				(u16 *) buf);
885 
886 	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
887 
888 	args[0] = 0x4300;
889 	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
890 
891 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
892 
893 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
894 
895 	par->board->wait_for_rdy(par);
896 	mutex_unlock(&(par->io_lock));
897 
898 }
899 
broadsheetfb_dpy_update(struct broadsheetfb_par * par)900 static void broadsheetfb_dpy_update(struct broadsheetfb_par *par)
901 {
902 	u16 args[5];
903 
904 	mutex_lock(&(par->io_lock));
905 	args[0] = 0x3 << 4;
906 	broadsheet_send_cmdargs(par, BS_CMD_LD_IMG, 1, args);
907 
908 	args[0] = 0x154;
909 	broadsheet_send_cmdargs(par, BS_CMD_WR_REG, 1, args);
910 	broadsheet_burst_write(par, (panel_table[par->panel_index].w *
911 					panel_table[par->panel_index].h)/2,
912 					(u16 *) par->info->screen_base);
913 
914 	broadsheet_send_command(par, BS_CMD_LD_IMG_END);
915 
916 	args[0] = 0x4300;
917 	broadsheet_send_cmdargs(par, BS_CMD_UPD_FULL, 1, args);
918 
919 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_TRG);
920 
921 	broadsheet_send_command(par, BS_CMD_WAIT_DSPE_FREND);
922 
923 	par->board->wait_for_rdy(par);
924 	mutex_unlock(&(par->io_lock));
925 }
926 
927 /* this is called back from the deferred io workqueue */
broadsheetfb_dpy_deferred_io(struct fb_info * info,struct list_head * pagelist)928 static void broadsheetfb_dpy_deferred_io(struct fb_info *info,
929 				struct list_head *pagelist)
930 {
931 	u16 y1 = 0, h = 0;
932 	int prev_index = -1;
933 	struct page *cur;
934 	struct fb_deferred_io *fbdefio = info->fbdefio;
935 	int h_inc;
936 	u16 yres = info->var.yres;
937 	u16 xres = info->var.xres;
938 
939 	/* height increment is fixed per page */
940 	h_inc = DIV_ROUND_UP(PAGE_SIZE , xres);
941 
942 	/* walk the written page list and swizzle the data */
943 	list_for_each_entry(cur, &fbdefio->pagelist, lru) {
944 		if (prev_index < 0) {
945 			/* just starting so assign first page */
946 			y1 = (cur->index << PAGE_SHIFT) / xres;
947 			h = h_inc;
948 		} else if ((prev_index + 1) == cur->index) {
949 			/* this page is consecutive so increase our height */
950 			h += h_inc;
951 		} else {
952 			/* page not consecutive, issue previous update first */
953 			broadsheetfb_dpy_update_pages(info->par, y1, y1 + h);
954 			/* start over with our non consecutive page */
955 			y1 = (cur->index << PAGE_SHIFT) / xres;
956 			h = h_inc;
957 		}
958 		prev_index = cur->index;
959 	}
960 
961 	/* if we still have any pages to update we do so now */
962 	if (h >= yres) {
963 		/* its a full screen update, just do it */
964 		broadsheetfb_dpy_update(info->par);
965 	} else {
966 		broadsheetfb_dpy_update_pages(info->par, y1,
967 						min((u16) (y1 + h), yres));
968 	}
969 }
970 
broadsheetfb_fillrect(struct fb_info * info,const struct fb_fillrect * rect)971 static void broadsheetfb_fillrect(struct fb_info *info,
972 				   const struct fb_fillrect *rect)
973 {
974 	struct broadsheetfb_par *par = info->par;
975 
976 	sys_fillrect(info, rect);
977 
978 	broadsheetfb_dpy_update(par);
979 }
980 
broadsheetfb_copyarea(struct fb_info * info,const struct fb_copyarea * area)981 static void broadsheetfb_copyarea(struct fb_info *info,
982 				   const struct fb_copyarea *area)
983 {
984 	struct broadsheetfb_par *par = info->par;
985 
986 	sys_copyarea(info, area);
987 
988 	broadsheetfb_dpy_update(par);
989 }
990 
broadsheetfb_imageblit(struct fb_info * info,const struct fb_image * image)991 static void broadsheetfb_imageblit(struct fb_info *info,
992 				const struct fb_image *image)
993 {
994 	struct broadsheetfb_par *par = info->par;
995 
996 	sys_imageblit(info, image);
997 
998 	broadsheetfb_dpy_update(par);
999 }
1000 
1001 /*
1002  * this is the slow path from userspace. they can seek and write to
1003  * the fb. it's inefficient to do anything less than a full screen draw
1004  */
broadsheetfb_write(struct fb_info * info,const char __user * buf,size_t count,loff_t * ppos)1005 static ssize_t broadsheetfb_write(struct fb_info *info, const char __user *buf,
1006 				size_t count, loff_t *ppos)
1007 {
1008 	struct broadsheetfb_par *par = info->par;
1009 	unsigned long p = *ppos;
1010 	void *dst;
1011 	int err = 0;
1012 	unsigned long total_size;
1013 
1014 	if (info->state != FBINFO_STATE_RUNNING)
1015 		return -EPERM;
1016 
1017 	total_size = info->fix.smem_len;
1018 
1019 	if (p > total_size)
1020 		return -EFBIG;
1021 
1022 	if (count > total_size) {
1023 		err = -EFBIG;
1024 		count = total_size;
1025 	}
1026 
1027 	if (count + p > total_size) {
1028 		if (!err)
1029 			err = -ENOSPC;
1030 
1031 		count = total_size - p;
1032 	}
1033 
1034 	dst = (void *)(info->screen_base + p);
1035 
1036 	if (copy_from_user(dst, buf, count))
1037 		err = -EFAULT;
1038 
1039 	if  (!err)
1040 		*ppos += count;
1041 
1042 	broadsheetfb_dpy_update(par);
1043 
1044 	return (err) ? err : count;
1045 }
1046 
1047 static struct fb_ops broadsheetfb_ops = {
1048 	.owner		= THIS_MODULE,
1049 	.fb_read        = fb_sys_read,
1050 	.fb_write	= broadsheetfb_write,
1051 	.fb_fillrect	= broadsheetfb_fillrect,
1052 	.fb_copyarea	= broadsheetfb_copyarea,
1053 	.fb_imageblit	= broadsheetfb_imageblit,
1054 };
1055 
1056 static struct fb_deferred_io broadsheetfb_defio = {
1057 	.delay		= HZ/4,
1058 	.deferred_io	= broadsheetfb_dpy_deferred_io,
1059 };
1060 
broadsheetfb_probe(struct platform_device * dev)1061 static int broadsheetfb_probe(struct platform_device *dev)
1062 {
1063 	struct fb_info *info;
1064 	struct broadsheet_board *board;
1065 	int retval = -ENOMEM;
1066 	int videomemorysize;
1067 	unsigned char *videomemory;
1068 	struct broadsheetfb_par *par;
1069 	int i;
1070 	int dpyw, dpyh;
1071 	int panel_index;
1072 
1073 	/* pick up board specific routines */
1074 	board = dev->dev.platform_data;
1075 	if (!board)
1076 		return -EINVAL;
1077 
1078 	/* try to count device specific driver, if can't, platform recalls */
1079 	if (!try_module_get(board->owner))
1080 		return -ENODEV;
1081 
1082 	info = framebuffer_alloc(sizeof(struct broadsheetfb_par), &dev->dev);
1083 	if (!info)
1084 		goto err;
1085 
1086 	switch (board->get_panel_type()) {
1087 	case 37:
1088 		panel_index = 1;
1089 		break;
1090 	case 97:
1091 		panel_index = 2;
1092 		break;
1093 	case 6:
1094 	default:
1095 		panel_index = 0;
1096 		break;
1097 	}
1098 
1099 	dpyw = panel_table[panel_index].w;
1100 	dpyh = panel_table[panel_index].h;
1101 
1102 	videomemorysize = roundup((dpyw*dpyh), PAGE_SIZE);
1103 
1104 	videomemory = vzalloc(videomemorysize);
1105 	if (!videomemory)
1106 		goto err_fb_rel;
1107 
1108 	info->screen_base = (char *)videomemory;
1109 	info->fbops = &broadsheetfb_ops;
1110 
1111 	broadsheetfb_var.xres = dpyw;
1112 	broadsheetfb_var.yres = dpyh;
1113 	broadsheetfb_var.xres_virtual = dpyw;
1114 	broadsheetfb_var.yres_virtual = dpyh;
1115 	info->var = broadsheetfb_var;
1116 
1117 	broadsheetfb_fix.line_length = dpyw;
1118 	info->fix = broadsheetfb_fix;
1119 	info->fix.smem_len = videomemorysize;
1120 	par = info->par;
1121 	par->panel_index = panel_index;
1122 	par->info = info;
1123 	par->board = board;
1124 	par->write_reg = broadsheet_write_reg;
1125 	par->read_reg = broadsheet_read_reg;
1126 	init_waitqueue_head(&par->waitq);
1127 
1128 	mutex_init(&par->io_lock);
1129 
1130 	info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
1131 
1132 	info->fbdefio = &broadsheetfb_defio;
1133 	fb_deferred_io_init(info);
1134 
1135 	retval = fb_alloc_cmap(&info->cmap, 16, 0);
1136 	if (retval < 0) {
1137 		dev_err(&dev->dev, "Failed to allocate colormap\n");
1138 		goto err_vfree;
1139 	}
1140 
1141 	/* set cmap */
1142 	for (i = 0; i < 16; i++)
1143 		info->cmap.red[i] = (((2*i)+1)*(0xFFFF))/32;
1144 	memcpy(info->cmap.green, info->cmap.red, sizeof(u16)*16);
1145 	memcpy(info->cmap.blue, info->cmap.red, sizeof(u16)*16);
1146 
1147 	retval = par->board->setup_irq(info);
1148 	if (retval < 0)
1149 		goto err_cmap;
1150 
1151 	/* this inits the dpy */
1152 	retval = board->init(par);
1153 	if (retval < 0)
1154 		goto err_free_irq;
1155 
1156 	broadsheet_identify(par);
1157 
1158 	broadsheet_init(par);
1159 
1160 	retval = register_framebuffer(info);
1161 	if (retval < 0)
1162 		goto err_free_irq;
1163 
1164 	platform_set_drvdata(dev, info);
1165 
1166 	retval = device_create_file(&dev->dev, &dev_attr_loadstore_waveform);
1167 	if (retval < 0)
1168 		goto err_unreg_fb;
1169 
1170 	fb_info(info, "Broadsheet frame buffer, using %dK of video memory\n",
1171 		videomemorysize >> 10);
1172 
1173 
1174 	return 0;
1175 
1176 err_unreg_fb:
1177 	unregister_framebuffer(info);
1178 err_free_irq:
1179 	board->cleanup(par);
1180 err_cmap:
1181 	fb_dealloc_cmap(&info->cmap);
1182 err_vfree:
1183 	vfree(videomemory);
1184 err_fb_rel:
1185 	framebuffer_release(info);
1186 err:
1187 	module_put(board->owner);
1188 	return retval;
1189 
1190 }
1191 
broadsheetfb_remove(struct platform_device * dev)1192 static int broadsheetfb_remove(struct platform_device *dev)
1193 {
1194 	struct fb_info *info = platform_get_drvdata(dev);
1195 
1196 	if (info) {
1197 		struct broadsheetfb_par *par = info->par;
1198 
1199 		device_remove_file(info->dev, &dev_attr_loadstore_waveform);
1200 		unregister_framebuffer(info);
1201 		fb_deferred_io_cleanup(info);
1202 		par->board->cleanup(par);
1203 		fb_dealloc_cmap(&info->cmap);
1204 		vfree((void *)info->screen_base);
1205 		module_put(par->board->owner);
1206 		framebuffer_release(info);
1207 	}
1208 	return 0;
1209 }
1210 
1211 static struct platform_driver broadsheetfb_driver = {
1212 	.probe	= broadsheetfb_probe,
1213 	.remove = broadsheetfb_remove,
1214 	.driver	= {
1215 		.owner	= THIS_MODULE,
1216 		.name	= "broadsheetfb",
1217 	},
1218 };
1219 module_platform_driver(broadsheetfb_driver);
1220 
1221 MODULE_DESCRIPTION("fbdev driver for Broadsheet controller");
1222 MODULE_AUTHOR("Jaya Kumar");
1223 MODULE_LICENSE("GPL");
1224