• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* #define DEBUG */
2 
3 #include <linux/module.h>
4 #include <linux/delay.h>
5 #include <linux/slab.h>
6 #include <linux/gpio.h>
7 #include <linux/spi/spi.h>
8 #include <linux/fb.h>
9 
10 #include <video/omapdss.h>
11 #include <video/omap-panel-data.h>
12 
13 #define BLIZZARD_REV_CODE                      0x00
14 #define BLIZZARD_CONFIG                        0x02
15 #define BLIZZARD_PLL_DIV                       0x04
16 #define BLIZZARD_PLL_LOCK_RANGE                0x06
17 #define BLIZZARD_PLL_CLOCK_SYNTH_0             0x08
18 #define BLIZZARD_PLL_CLOCK_SYNTH_1             0x0a
19 #define BLIZZARD_PLL_MODE                      0x0c
20 #define BLIZZARD_CLK_SRC                       0x0e
21 #define BLIZZARD_MEM_BANK0_ACTIVATE            0x10
22 #define BLIZZARD_MEM_BANK0_STATUS              0x14
23 #define BLIZZARD_PANEL_CONFIGURATION           0x28
24 #define BLIZZARD_HDISP                         0x2a
25 #define BLIZZARD_HNDP                          0x2c
26 #define BLIZZARD_VDISP0                        0x2e
27 #define BLIZZARD_VDISP1                        0x30
28 #define BLIZZARD_VNDP                          0x32
29 #define BLIZZARD_HSW                           0x34
30 #define BLIZZARD_VSW                           0x38
31 #define BLIZZARD_DISPLAY_MODE                  0x68
32 #define BLIZZARD_INPUT_WIN_X_START_0           0x6c
33 #define BLIZZARD_DATA_SOURCE_SELECT            0x8e
34 #define BLIZZARD_DISP_MEM_DATA_PORT            0x90
35 #define BLIZZARD_DISP_MEM_READ_ADDR0           0x92
36 #define BLIZZARD_POWER_SAVE                    0xE6
37 #define BLIZZARD_NDISP_CTRL_STATUS             0xE8
38 
39 /* Data source select */
40 /* For S1D13745 */
41 #define BLIZZARD_SRC_WRITE_LCD_BACKGROUND	0x00
42 #define BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE	0x01
43 #define BLIZZARD_SRC_WRITE_OVERLAY_ENABLE	0x04
44 #define BLIZZARD_SRC_DISABLE_OVERLAY		0x05
45 /* For S1D13744 */
46 #define BLIZZARD_SRC_WRITE_LCD			0x00
47 #define BLIZZARD_SRC_BLT_LCD			0x06
48 
49 #define BLIZZARD_COLOR_RGB565			0x01
50 #define BLIZZARD_COLOR_YUV420			0x09
51 
52 #define BLIZZARD_VERSION_S1D13745		0x01	/* Hailstorm */
53 #define BLIZZARD_VERSION_S1D13744		0x02	/* Blizzard */
54 
55 #define MIPID_CMD_READ_DISP_ID		0x04
56 #define MIPID_CMD_READ_RED		0x06
57 #define MIPID_CMD_READ_GREEN		0x07
58 #define MIPID_CMD_READ_BLUE		0x08
59 #define MIPID_CMD_READ_DISP_STATUS	0x09
60 #define MIPID_CMD_RDDSDR		0x0F
61 #define MIPID_CMD_SLEEP_IN		0x10
62 #define MIPID_CMD_SLEEP_OUT		0x11
63 #define MIPID_CMD_DISP_OFF		0x28
64 #define MIPID_CMD_DISP_ON		0x29
65 
66 static struct panel_drv_data {
67 	struct mutex lock;
68 
69 	struct omap_dss_device *dssdev;
70 	struct spi_device *spidev;
71 
72 	int blizzard_ver;
73 } s_drv_data;
74 
75 
76 static inline
get_board_data(const struct omap_dss_device * dssdev)77 struct panel_n8x0_data *get_board_data(const struct omap_dss_device *dssdev)
78 {
79 	return dssdev->data;
80 }
81 
82 static inline
get_drv_data(const struct omap_dss_device * dssdev)83 struct panel_drv_data *get_drv_data(const struct omap_dss_device *dssdev)
84 {
85 	return &s_drv_data;
86 }
87 
88 
blizzard_cmd(u8 cmd)89 static inline void blizzard_cmd(u8 cmd)
90 {
91 	omap_rfbi_write_command(&cmd, 1);
92 }
93 
blizzard_write(u8 cmd,const u8 * buf,int len)94 static inline void blizzard_write(u8 cmd, const u8 *buf, int len)
95 {
96 	omap_rfbi_write_command(&cmd, 1);
97 	omap_rfbi_write_data(buf, len);
98 }
99 
blizzard_read(u8 cmd,u8 * buf,int len)100 static inline void blizzard_read(u8 cmd, u8 *buf, int len)
101 {
102 	omap_rfbi_write_command(&cmd, 1);
103 	omap_rfbi_read_data(buf, len);
104 }
105 
blizzard_read_reg(u8 cmd)106 static u8 blizzard_read_reg(u8 cmd)
107 {
108 	u8 data;
109 	blizzard_read(cmd, &data, 1);
110 	return data;
111 }
112 
blizzard_ctrl_setup_update(struct omap_dss_device * dssdev,int x,int y,int w,int h)113 static void blizzard_ctrl_setup_update(struct omap_dss_device *dssdev,
114 		int x, int y, int w, int h)
115 {
116 	struct panel_drv_data *ddata = get_drv_data(dssdev);
117 	u8 tmp[18];
118 	int x_end, y_end;
119 
120 	x_end = x + w - 1;
121 	y_end = y + h - 1;
122 
123 	tmp[0] = x;
124 	tmp[1] = x >> 8;
125 	tmp[2] = y;
126 	tmp[3] = y >> 8;
127 	tmp[4] = x_end;
128 	tmp[5] = x_end >> 8;
129 	tmp[6] = y_end;
130 	tmp[7] = y_end >> 8;
131 
132 	/* scaling? */
133 	tmp[8] = x;
134 	tmp[9] = x >> 8;
135 	tmp[10] = y;
136 	tmp[11] = y >> 8;
137 	tmp[12] = x_end;
138 	tmp[13] = x_end >> 8;
139 	tmp[14] = y_end;
140 	tmp[15] = y_end >> 8;
141 
142 	tmp[16] = BLIZZARD_COLOR_RGB565;
143 
144 	if (ddata->blizzard_ver == BLIZZARD_VERSION_S1D13745)
145 		tmp[17] = BLIZZARD_SRC_WRITE_LCD_BACKGROUND;
146 	else
147 		tmp[17] = ddata->blizzard_ver == BLIZZARD_VERSION_S1D13744 ?
148 			BLIZZARD_SRC_WRITE_LCD :
149 			BLIZZARD_SRC_WRITE_LCD_DESTRUCTIVE;
150 
151 	omapdss_rfbi_set_pixel_size(dssdev, 16);
152 	omapdss_rfbi_set_data_lines(dssdev, 8);
153 
154 	omap_rfbi_configure(dssdev);
155 
156 	blizzard_write(BLIZZARD_INPUT_WIN_X_START_0, tmp, 18);
157 
158 	omapdss_rfbi_set_pixel_size(dssdev, 16);
159 	omapdss_rfbi_set_data_lines(dssdev, 16);
160 
161 	omap_rfbi_configure(dssdev);
162 }
163 
mipid_transfer(struct spi_device * spi,int cmd,const u8 * wbuf,int wlen,u8 * rbuf,int rlen)164 static void mipid_transfer(struct spi_device *spi, int cmd, const u8 *wbuf,
165 		int wlen, u8 *rbuf, int rlen)
166 {
167 	struct spi_message	m;
168 	struct spi_transfer	*x, xfer[4];
169 	u16			w;
170 	int			r;
171 
172 	spi_message_init(&m);
173 
174 	memset(xfer, 0, sizeof(xfer));
175 	x = &xfer[0];
176 
177 	cmd &=  0xff;
178 	x->tx_buf		= &cmd;
179 	x->bits_per_word	= 9;
180 	x->len			= 2;
181 	spi_message_add_tail(x, &m);
182 
183 	if (wlen) {
184 		x++;
185 		x->tx_buf		= wbuf;
186 		x->len			= wlen;
187 		x->bits_per_word	= 9;
188 		spi_message_add_tail(x, &m);
189 	}
190 
191 	if (rlen) {
192 		x++;
193 		x->rx_buf	= &w;
194 		x->len		= 1;
195 		spi_message_add_tail(x, &m);
196 
197 		if (rlen > 1) {
198 			/* Arrange for the extra clock before the first
199 			 * data bit.
200 			 */
201 			x->bits_per_word = 9;
202 			x->len		 = 2;
203 
204 			x++;
205 			x->rx_buf	 = &rbuf[1];
206 			x->len		 = rlen - 1;
207 			spi_message_add_tail(x, &m);
208 		}
209 	}
210 
211 	r = spi_sync(spi, &m);
212 	if (r < 0)
213 		dev_dbg(&spi->dev, "spi_sync %d\n", r);
214 
215 	if (rlen)
216 		rbuf[0] = w & 0xff;
217 }
218 
mipid_cmd(struct spi_device * spi,int cmd)219 static inline void mipid_cmd(struct spi_device *spi, int cmd)
220 {
221 	mipid_transfer(spi, cmd, NULL, 0, NULL, 0);
222 }
223 
mipid_write(struct spi_device * spi,int reg,const u8 * buf,int len)224 static inline void mipid_write(struct spi_device *spi,
225 		int reg, const u8 *buf, int len)
226 {
227 	mipid_transfer(spi, reg, buf, len, NULL, 0);
228 }
229 
mipid_read(struct spi_device * spi,int reg,u8 * buf,int len)230 static inline void mipid_read(struct spi_device *spi,
231 		int reg, u8 *buf, int len)
232 {
233 	mipid_transfer(spi, reg, NULL, 0, buf, len);
234 }
235 
set_data_lines(struct spi_device * spi,int data_lines)236 static void set_data_lines(struct spi_device *spi, int data_lines)
237 {
238 	u16 par;
239 
240 	switch (data_lines) {
241 	case 16:
242 		par = 0x150;
243 		break;
244 	case 18:
245 		par = 0x160;
246 		break;
247 	case 24:
248 		par = 0x170;
249 		break;
250 	}
251 
252 	mipid_write(spi, 0x3a, (u8 *)&par, 2);
253 }
254 
send_init_string(struct spi_device * spi)255 static void send_init_string(struct spi_device *spi)
256 {
257 	u16 initpar[] = { 0x0102, 0x0100, 0x0100 };
258 	mipid_write(spi, 0xc2, (u8 *)initpar, sizeof(initpar));
259 }
260 
send_display_on(struct spi_device * spi)261 static void send_display_on(struct spi_device *spi)
262 {
263 	mipid_cmd(spi, MIPID_CMD_DISP_ON);
264 }
265 
send_display_off(struct spi_device * spi)266 static void send_display_off(struct spi_device *spi)
267 {
268 	mipid_cmd(spi, MIPID_CMD_DISP_OFF);
269 }
270 
send_sleep_out(struct spi_device * spi)271 static void send_sleep_out(struct spi_device *spi)
272 {
273 	mipid_cmd(spi, MIPID_CMD_SLEEP_OUT);
274 	msleep(120);
275 }
276 
send_sleep_in(struct spi_device * spi)277 static void send_sleep_in(struct spi_device *spi)
278 {
279 	mipid_cmd(spi, MIPID_CMD_SLEEP_IN);
280 	msleep(50);
281 }
282 
n8x0_panel_power_on(struct omap_dss_device * dssdev)283 static int n8x0_panel_power_on(struct omap_dss_device *dssdev)
284 {
285 	int r;
286 	struct panel_n8x0_data *bdata = get_board_data(dssdev);
287 	struct panel_drv_data *ddata = get_drv_data(dssdev);
288 	struct spi_device *spi = ddata->spidev;
289 	u8 rev, conf;
290 	u8 display_id[3];
291 	const char *panel_name;
292 
293 	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
294 		return 0;
295 
296 	gpio_direction_output(bdata->ctrl_pwrdown, 1);
297 
298 	omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res,
299 		dssdev->panel.timings.y_res);
300 	omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size);
301 	omapdss_rfbi_set_data_lines(dssdev, dssdev->phy.rfbi.data_lines);
302 	omapdss_rfbi_set_interface_timings(dssdev, &dssdev->ctrl.rfbi_timings);
303 
304 	r = omapdss_rfbi_display_enable(dssdev);
305 	if (r)
306 		goto err_rfbi_en;
307 
308 	rev = blizzard_read_reg(BLIZZARD_REV_CODE);
309 	conf = blizzard_read_reg(BLIZZARD_CONFIG);
310 
311 	switch (rev & 0xfc) {
312 	case 0x9c:
313 		ddata->blizzard_ver = BLIZZARD_VERSION_S1D13744;
314 		dev_info(&dssdev->dev, "s1d13744 LCD controller rev %d "
315 			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
316 		break;
317 	case 0xa4:
318 		ddata->blizzard_ver = BLIZZARD_VERSION_S1D13745;
319 		dev_info(&dssdev->dev, "s1d13745 LCD controller rev %d "
320 			"initialized (CNF pins %x)\n", rev & 0x03, conf & 0x07);
321 		break;
322 	default:
323 		dev_err(&dssdev->dev, "invalid s1d1374x revision %02x\n", rev);
324 		r = -ENODEV;
325 		goto err_inv_chip;
326 	}
327 
328 	/* panel */
329 
330 	gpio_direction_output(bdata->panel_reset, 1);
331 
332 	mipid_read(spi, MIPID_CMD_READ_DISP_ID, display_id, 3);
333 	dev_dbg(&spi->dev, "MIPI display ID: %02x%02x%02x\n",
334 			display_id[0], display_id[1], display_id[2]);
335 
336 	switch (display_id[0]) {
337 	case 0x45:
338 		panel_name = "lph8923";
339 		break;
340 	case 0x83:
341 		panel_name = "ls041y3";
342 		break;
343 	default:
344 		dev_err(&dssdev->dev, "invalid display ID 0x%x\n",
345 				display_id[0]);
346 		r = -ENODEV;
347 		goto err_inv_panel;
348 	}
349 
350 	dev_info(&dssdev->dev, "%s rev %02x LCD detected\n",
351 			panel_name, display_id[1]);
352 
353 	send_sleep_out(spi);
354 	send_init_string(spi);
355 	set_data_lines(spi, 24);
356 	send_display_on(spi);
357 
358 	return 0;
359 
360 err_inv_panel:
361 	/*
362 	 * HACK: we should turn off the panel here, but there is some problem
363 	 * with the initialization sequence, and we fail to init the panel if we
364 	 * have turned it off
365 	 */
366 	/* gpio_direction_output(bdata->panel_reset, 0); */
367 err_inv_chip:
368 	omapdss_rfbi_display_disable(dssdev);
369 err_rfbi_en:
370 	gpio_direction_output(bdata->ctrl_pwrdown, 0);
371 	return r;
372 }
373 
n8x0_panel_power_off(struct omap_dss_device * dssdev)374 static void n8x0_panel_power_off(struct omap_dss_device *dssdev)
375 {
376 	struct panel_n8x0_data *bdata = get_board_data(dssdev);
377 	struct panel_drv_data *ddata = get_drv_data(dssdev);
378 	struct spi_device *spi = ddata->spidev;
379 
380 	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
381 		return;
382 
383 	send_display_off(spi);
384 	send_sleep_in(spi);
385 
386 	/*
387 	 * HACK: we should turn off the panel here, but there is some problem
388 	 * with the initialization sequence, and we fail to init the panel if we
389 	 * have turned it off
390 	 */
391 	/* gpio_direction_output(bdata->panel_reset, 0); */
392 	gpio_direction_output(bdata->ctrl_pwrdown, 0);
393 	omapdss_rfbi_display_disable(dssdev);
394 }
395 
396 static const struct rfbi_timings n8x0_panel_timings = {
397 	.cs_on_time     = 0,
398 
399 	.we_on_time     = 9000,
400 	.we_off_time    = 18000,
401 	.we_cycle_time  = 36000,
402 
403 	.re_on_time     = 9000,
404 	.re_off_time    = 27000,
405 	.re_cycle_time  = 36000,
406 
407 	.access_time    = 27000,
408 	.cs_off_time    = 36000,
409 
410 	.cs_pulse_width = 0,
411 };
412 
n8x0_panel_probe(struct omap_dss_device * dssdev)413 static int n8x0_panel_probe(struct omap_dss_device *dssdev)
414 {
415 	struct panel_n8x0_data *bdata = get_board_data(dssdev);
416 	struct panel_drv_data *ddata;
417 	int r;
418 
419 	dev_dbg(&dssdev->dev, "probe\n");
420 
421 	if (!bdata)
422 		return -EINVAL;
423 
424 	s_drv_data.dssdev = dssdev;
425 
426 	ddata = &s_drv_data;
427 
428 	mutex_init(&ddata->lock);
429 
430 	dssdev->panel.timings.x_res = 800;
431 	dssdev->panel.timings.y_res = 480;
432 	dssdev->ctrl.pixel_size = 16;
433 	dssdev->ctrl.rfbi_timings = n8x0_panel_timings;
434 	dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
435 
436 	if (gpio_is_valid(bdata->panel_reset)) {
437 		r = devm_gpio_request_one(&dssdev->dev, bdata->panel_reset,
438 				GPIOF_OUT_INIT_LOW, "PANEL RESET");
439 		if (r)
440 			return r;
441 	}
442 
443 	if (gpio_is_valid(bdata->ctrl_pwrdown)) {
444 		r = devm_gpio_request_one(&dssdev->dev, bdata->ctrl_pwrdown,
445 				GPIOF_OUT_INIT_LOW, "PANEL PWRDOWN");
446 		if (r)
447 			return r;
448 	}
449 
450 	return 0;
451 }
452 
n8x0_panel_remove(struct omap_dss_device * dssdev)453 static void n8x0_panel_remove(struct omap_dss_device *dssdev)
454 {
455 	dev_dbg(&dssdev->dev, "remove\n");
456 
457 	dev_set_drvdata(&dssdev->dev, NULL);
458 }
459 
n8x0_panel_enable(struct omap_dss_device * dssdev)460 static int n8x0_panel_enable(struct omap_dss_device *dssdev)
461 {
462 	struct panel_drv_data *ddata = get_drv_data(dssdev);
463 	int r;
464 
465 	dev_dbg(&dssdev->dev, "enable\n");
466 
467 	mutex_lock(&ddata->lock);
468 
469 	rfbi_bus_lock();
470 
471 	r = n8x0_panel_power_on(dssdev);
472 
473 	rfbi_bus_unlock();
474 
475 	if (r) {
476 		mutex_unlock(&ddata->lock);
477 		return r;
478 	}
479 
480 	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
481 
482 	mutex_unlock(&ddata->lock);
483 
484 	return 0;
485 }
486 
n8x0_panel_disable(struct omap_dss_device * dssdev)487 static void n8x0_panel_disable(struct omap_dss_device *dssdev)
488 {
489 	struct panel_drv_data *ddata = get_drv_data(dssdev);
490 
491 	dev_dbg(&dssdev->dev, "disable\n");
492 
493 	mutex_lock(&ddata->lock);
494 
495 	rfbi_bus_lock();
496 
497 	n8x0_panel_power_off(dssdev);
498 
499 	rfbi_bus_unlock();
500 
501 	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
502 
503 	mutex_unlock(&ddata->lock);
504 }
505 
n8x0_panel_get_resolution(struct omap_dss_device * dssdev,u16 * xres,u16 * yres)506 static void n8x0_panel_get_resolution(struct omap_dss_device *dssdev,
507 		u16 *xres, u16 *yres)
508 {
509 	*xres = dssdev->panel.timings.x_res;
510 	*yres = dssdev->panel.timings.y_res;
511 }
512 
update_done(void * data)513 static void update_done(void *data)
514 {
515 	rfbi_bus_unlock();
516 }
517 
n8x0_panel_update(struct omap_dss_device * dssdev,u16 x,u16 y,u16 w,u16 h)518 static int n8x0_panel_update(struct omap_dss_device *dssdev,
519 		u16 x, u16 y, u16 w, u16 h)
520 {
521 	struct panel_drv_data *ddata = get_drv_data(dssdev);
522 	u16 dw, dh;
523 
524 	dev_dbg(&dssdev->dev, "update\n");
525 
526 	dw = dssdev->panel.timings.x_res;
527 	dh = dssdev->panel.timings.y_res;
528 
529 	if (x != 0 || y != 0 || w != dw || h != dh) {
530 		dev_err(&dssdev->dev, "invaid update region %d, %d, %d, %d\n",
531 			x, y, w, h);
532 		return -EINVAL;
533 	}
534 
535 	mutex_lock(&ddata->lock);
536 	rfbi_bus_lock();
537 
538 	blizzard_ctrl_setup_update(dssdev, x, y, w, h);
539 
540 	omap_rfbi_update(dssdev, update_done, NULL);
541 
542 	mutex_unlock(&ddata->lock);
543 
544 	return 0;
545 }
546 
n8x0_panel_sync(struct omap_dss_device * dssdev)547 static int n8x0_panel_sync(struct omap_dss_device *dssdev)
548 {
549 	struct panel_drv_data *ddata = get_drv_data(dssdev);
550 
551 	dev_dbg(&dssdev->dev, "sync\n");
552 
553 	mutex_lock(&ddata->lock);
554 	rfbi_bus_lock();
555 	rfbi_bus_unlock();
556 	mutex_unlock(&ddata->lock);
557 
558 	return 0;
559 }
560 
561 static struct omap_dss_driver n8x0_panel_driver = {
562 	.probe		= n8x0_panel_probe,
563 	.remove		= n8x0_panel_remove,
564 
565 	.enable		= n8x0_panel_enable,
566 	.disable	= n8x0_panel_disable,
567 
568 	.update		= n8x0_panel_update,
569 	.sync		= n8x0_panel_sync,
570 
571 	.get_resolution	= n8x0_panel_get_resolution,
572 	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
573 
574 	.driver         = {
575 		.name   = "n8x0_panel",
576 		.owner  = THIS_MODULE,
577 	},
578 };
579 
580 /* PANEL */
581 
mipid_spi_probe(struct spi_device * spi)582 static int mipid_spi_probe(struct spi_device *spi)
583 {
584 	int r;
585 
586 	dev_dbg(&spi->dev, "mipid_spi_probe\n");
587 
588 	spi->mode = SPI_MODE_0;
589 
590 	s_drv_data.spidev = spi;
591 
592 	r = omap_dss_register_driver(&n8x0_panel_driver);
593 	if (r)
594 		pr_err("n8x0_panel: dss driver registration failed\n");
595 
596 	return r;
597 }
598 
mipid_spi_remove(struct spi_device * spi)599 static int mipid_spi_remove(struct spi_device *spi)
600 {
601 	dev_dbg(&spi->dev, "mipid_spi_remove\n");
602 	omap_dss_unregister_driver(&n8x0_panel_driver);
603 	return 0;
604 }
605 
606 static struct spi_driver mipid_spi_driver = {
607 	.driver = {
608 		.name	= "lcd_mipid",
609 		.owner	= THIS_MODULE,
610 	},
611 	.probe	= mipid_spi_probe,
612 	.remove	= mipid_spi_remove,
613 };
614 module_spi_driver(mipid_spi_driver);
615 
616 MODULE_LICENSE("GPL");
617