1 /*
2 * (C) Copyright 2020 Rockchip Electronics Co., Ltd
3 *
4 * SPDX-License-Identifier: GPL-2.0+
5 * Author: Wenping Zhang <wenping.zhang@rock-chips.com>
6 */
7 #include <common.h>
8 #include <dm.h>
9 #include <stdio.h>
10 #include <errno.h>
11 #include <mapmem.h>
12 #include <stdlib.h>
13 #include <asm/arch/vendor.h>
14 #include <dm/of_access.h>
15 #include <dm/uclass.h>
16 #include <dm/uclass-id.h>
17 #include <boot_rkimg.h>
18 #include <rk_eink.h>
19 #include <backlight.h>
20 #include "rk_ebc.h"
21 #include "epdlut/epd_lut.h"
22
23 #define PART_WAVEFORM "waveform"
24 #define EINK_LOGO_PART_MAGIC "RKEL"
25 #define EINK_LOGO_IMAGE_MAGIC "GR04"
26 /*
27 * grayscale logo partition format:
28 * block0:
29 * struct logo_part_header part_header;
30 * struct grayscale_header logo1_header;
31 * struct grayscale_header logo2_header;
32 * struct grayscale_header logo3_header;
33 * struct grayscale_header logo4_header;
34 * ....
35 *
36 * block 1:
37 * logo1_image
38 *
39 * .....
40 * block m:
41 * logo2_image
42 *
43 * ........
44 * block n:
45 * logo3_image
46 *
47 * ........
48 * block i:
49 * logoi_image
50 */
51
52 //logo partition Header, 64byte
53 struct logo_part_header {
54 char magic[4]; /* must be "RKEL" */
55 u32 totoal_size;
56 u32 screen_width;
57 u32 screen_height;
58 u32 logo_count;
59 u8 version[4];
60 u32 rsv[10];
61 } __packed;
62
63 // logo image header,32 byte
64 struct grayscale_header {
65 char magic[4]; /* must be "GR04" */
66 u16 x;
67 u16 y;
68 u16 w;
69 u16 h;
70 u32 logo_type;
71 u32 data_offset; /* image offset in byte */
72 u32 data_size; /* image size in byte */
73 u32 rsv[2];
74 } __packed;
75
76 /*
77 * The start address of logo image in logo.img must be aligned in 512 bytes,
78 * so the header size must be times of 512 bytes. Here we fix the size to 512
79 * bytes, so the count of logo image can only support up to 14.
80 */
81 struct logo_info {
82 struct logo_part_header part_hdr;
83 struct grayscale_header img_hdr[14];
84 } __packed;
85
86 struct rockchip_eink_display_priv {
87 struct udevice *dev;
88 struct udevice *ebc_tcon_dev;
89 struct udevice *ebc_pwr_dev;
90 int vcom;
91 struct udevice *backlight;
92 };
93
94 enum {
95 EBC_PWR_DOWN = 0,
96 EBC_PWR_ON = 1,
97 };
98
99 #define EINK_VCOM_ID 17
100 #define EINK_VCOM_MAX 64
101 #define VCOM_DEFAULT_VALUE 1650
102
103 static struct logo_info eink_logo_info;
104 static struct udevice *eink_dev;
105 static volatile int last_logo_type = -1;
read_vcom_from_vendor(void)106 static int read_vcom_from_vendor(void)
107 {
108 int ret = 0;
109 char vcom_str[EINK_VCOM_MAX] = {0};
110 char vcom_args[EINK_VCOM_MAX] = {0};
111
112 /* Read vcom value from vendor storage part */
113 ret = vendor_storage_read(EINK_VCOM_ID, vcom_str, (EINK_VCOM_MAX - 1));
114 if (ret > 0) {
115 snprintf(vcom_args, strlen(vcom_str) + 15, "ebc_pmic.vcom=%s", vcom_str);
116 printf("eink update bootargs: %s\n", vcom_args);
117 env_update("bootargs", vcom_args);
118 } else {
119 return ret;
120 }
121
122 return atoi(vcom_str);
123 }
124
read_waveform(struct udevice * dev)125 static int read_waveform(struct udevice *dev)
126 {
127 int cnt, start, ret;
128 disk_partition_t part;
129 struct blk_desc *dev_desc;
130 struct ebc_panel *plat = dev_get_platdata(dev);
131
132 dev_desc = rockchip_get_bootdev();
133 if (!dev_desc) {
134 printf("%s: Could not find device\n", __func__);
135 return -EIO;
136 }
137 if (part_get_info_by_name(dev_desc, PART_WAVEFORM, &part) < 0) {
138 printf("Get waveform partition failed\n");
139 return -ENODEV;
140 }
141 cnt = plat->lut_pbuf_size / RK_BLK_SIZE;
142 start = part.start;
143 ret = blk_dread(dev_desc, start, cnt, (void *)plat->lut_pbuf);
144 if (ret != cnt)
145 printf("Try to read %d blocks failed, only read %d\n",
146 cnt, ret);
147
148 flush_dcache_range((ulong)plat->lut_pbuf,
149 ALIGN((ulong)plat->lut_pbuf + cnt,
150 CONFIG_SYS_CACHELINE_SIZE));
151 ret = epd_lut_from_mem_init(plat->lut_pbuf, &plat->lut_ops);
152 if (ret < 0) {
153 printf("lut init failed\n");
154 return -EINVAL;
155 }
156
157 return 0;
158 }
159
aligned_image_size_4k(struct udevice * dev)160 static u32 aligned_image_size_4k(struct udevice *dev)
161 {
162 struct ebc_panel *plat = dev_get_platdata(dev);
163 u32 w = plat->vir_width;
164 u32 h = plat->vir_height;
165
166 return ALIGN((w * h) >> 1, 4096);
167 }
168
169 /*
170 * This driver load the grayscale image from flash,
171 * and put it in the reserve memory which define in dts:
172 * display_reserved: framebuffer@10000000 {
173 * reg = <0x0 0x10000000 0x0 0x2000000>;
174 * no-map;
175 * };
176 * Every image logo size must be aligned in 4K, make sure
177 * kernel can use it rightly, the buffer of LOGO image is
178 * put in order of below map:
179 * |---reset logo ---|
180 * |---uboot logo ---|
181 * |---kernel logo ---|
182 * |---charge_0 logo ---|
183 * |---charge_1 logo ---|
184 * |---charge_2 logo ---|
185 * |---charge_3 logo ---|
186 * |---charge_4 logo ---|
187 * |---charge_5 logo ---|
188 * |---battery low logo---|
189 * |---temp un-mirror buffer--|
190 */
get_addr_by_type(struct udevice * dev,u32 logo_type)191 static int get_addr_by_type(struct udevice *dev, u32 logo_type)
192 {
193 u32 offset, indx, img_size;
194 struct ebc_panel *plat = dev_get_platdata(dev);
195
196 if (plat->disp_pbuf_size == 0 || !plat->disp_pbuf) {
197 printf("invalid display buffer, please check dts\n");
198 return -EINVAL;
199 }
200 indx = ffs(logo_type);
201 img_size = aligned_image_size_4k(dev);
202 offset = img_size * indx;
203 if (offset + img_size > plat->disp_pbuf_size) {
204 printf("reserve display memory size is not enough\n");
205 return -EINVAL;
206 }
207
208 switch (logo_type) {
209 case EINK_LOGO_RESET:
210 case EINK_LOGO_UBOOT:
211 case EINK_LOGO_KERNEL:
212 case EINK_LOGO_CHARGING_0:
213 case EINK_LOGO_CHARGING_1:
214 case EINK_LOGO_CHARGING_2:
215 case EINK_LOGO_CHARGING_3:
216 case EINK_LOGO_CHARGING_4:
217 case EINK_LOGO_CHARGING_5:
218 case EINK_LOGO_CHARGING_LOWPOWER:
219 case EINK_LOGO_POWEROFF:
220 /*
221 * The MIRROR_TEMP_BUF is used to save the
222 * non-mirror image data.
223 */
224 case EINK_LOGO_UNMIRROR_TEMP_BUF:
225 return (plat->disp_pbuf + offset);
226 default:
227 printf("invalid logo type[%d]\n", logo_type);
228 }
229
230 return -EINVAL;
231 }
232
read_header(struct blk_desc * dev_desc,disk_partition_t * part,struct logo_info * header)233 static int read_header(struct blk_desc *dev_desc,
234 disk_partition_t *part,
235 struct logo_info *header)
236 {
237 int i;
238 struct logo_part_header *part_hdr = &header->part_hdr;
239
240 if (blk_dread(dev_desc, part->start, 1, header) != 1)
241 return -EIO;
242
243 if (memcmp(part_hdr->magic, EINK_LOGO_PART_MAGIC, 4)) {
244 printf("partition header is invalid\n");
245 return -EINVAL;
246 }
247 if (part_hdr->logo_count == 0) {
248 printf("the count of logo image is 0\n");
249 return -EINVAL;
250 }
251 for (i = 0; i < part_hdr->logo_count; i++) {
252 struct grayscale_header *img_hdr = &header->img_hdr[i];
253
254 if (memcmp(img_hdr->magic, EINK_LOGO_IMAGE_MAGIC, 4)) {
255 printf("image[%d] header '%s' is invalid\n", i,
256 img_hdr->magic);
257 return -EINVAL;
258 }
259 }
260
261 return 0;
262 }
263
read_grayscale(struct blk_desc * dev_desc,disk_partition_t * part,u32 offset,u32 size,void * buf)264 static int read_grayscale(struct blk_desc *dev_desc,
265 disk_partition_t *part, u32 offset,
266 u32 size, void *buf)
267 {
268 u32 blk_start, blk_offset, blk_count;
269
270 blk_offset = DIV_ROUND_UP(offset, dev_desc->blksz);
271 blk_start = part->start + blk_offset;
272 blk_count = DIV_ROUND_UP(size, dev_desc->blksz);
273
274 debug("blk_offset=%d, blk_start=%d,blk_count=%d,out buf=%p\n",
275 blk_offset, blk_start, blk_count, buf);
276 if (blk_dread(dev_desc, blk_start, blk_count, buf) != blk_count) {
277 printf("read grayscale data failed\n");
278 return -EIO;
279 }
280
281 return 0;
282 }
283
image_rearrange(u8 * in_buf,u8 * out_buf,u16 w,u16 h)284 static int image_rearrange(u8 *in_buf, u8 *out_buf, u16 w, u16 h)
285 {
286 int i, j;
287 u8 in_data;
288 u8 *out_buf_tmp;
289
290 if (!in_buf || !out_buf) {
291 printf("rearrange in buffer or out buffer is NULL\n");
292 return -EINVAL;
293 }
294
295 for (i = 0; i < h; i += 2) {
296 out_buf_tmp = out_buf + (i * w / 2);
297 for (j = 0; j < w / 2; j++) {
298 in_data = *in_buf++;
299 *(out_buf_tmp + j * 2) = in_data & 0x0f;
300 *(out_buf_tmp + j * 2 + 1) = (in_data >> 4) & 0x0f;
301 }
302 for (j = 0; j < w / 2; j++) {
303 in_data = *in_buf++;
304 *(out_buf_tmp + j * 2) |= (in_data << 4) & 0xf0;
305 *(out_buf_tmp + j * 2 + 1) |= in_data & 0xf0;
306 }
307 }
308
309 return 0;
310 }
311
image_mirror(u8 * in_buf,u8 * out_buf,u16 w,u16 h)312 static int image_mirror(u8 *in_buf, u8 *out_buf, u16 w, u16 h)
313 {
314 int i;
315
316 if (!in_buf || !out_buf) {
317 printf("mirror in buffer or out buffer is NULL\n");
318 return -EINVAL;
319 }
320
321 for (i = 0; i < h; i++) {
322 u16 column_len = w / 2;
323 u8 *column_in = in_buf + i * column_len;
324 u8 *column_out = out_buf + (h - i - 1) * column_len;
325
326 memcpy(column_out, column_in, column_len);
327 }
328
329 return 0;
330 }
331
332 /*
333 * The eink kernel driver need last frame to do part refresh,
334 * so we need to transfer two images to kernel, which is kernel
335 * logo and the logo displayed in uboot.
336 *
337 * this function use logo type bitmap to indicate several logo.
338 * u32 needed_logo: we only load needed logo image into ram, such as
339 * uboot logo + kernel logo or charger logo + kernel
340 * logo
341 * u32 *loaded_logo: because the needed logo may not exist in logo.img,
342 * store the really loaded logo in para loaded_logo.
343 */
read_needed_logo_from_partition(struct udevice * dev,u32 needed_logo,u32 * loaded_logo)344 static int read_needed_logo_from_partition(struct udevice *dev,
345 u32 needed_logo,
346 u32 *loaded_logo)
347 {
348 int ret, i;
349 disk_partition_t part;
350 struct blk_desc *dev_desc;
351 struct logo_info *hdr = &eink_logo_info;
352 struct logo_part_header *part_hdr = &hdr->part_hdr;
353 struct ebc_panel *panel = dev_get_platdata(dev);
354 u32 logo = needed_logo & (~(*loaded_logo));
355
356 if (!logo) {
357 printf("logo[0x%x] is already loaded, just return!\n",
358 needed_logo);
359 return 0;
360 }
361 dev_desc = rockchip_get_bootdev();
362 if (!dev_desc) {
363 printf("%s: Could not find device\n", __func__);
364 return -EIO;
365 }
366
367 if (part_get_info_by_name(dev_desc, PART_LOGO, &part) < 0)
368 return -ENODEV;
369
370 ret = read_header(dev_desc, &part, hdr);
371 if (ret < 0) {
372 printf("eink logo read header failed,ret = %d\n", ret);
373 return -EINVAL;
374 }
375 if (part_hdr->screen_width != panel->vir_width ||
376 part_hdr->screen_height != panel->vir_height){
377 printf("logo size(%dx%d) is not same as screen size(%dx%d)\n",
378 part_hdr->screen_width, part_hdr->screen_height,
379 panel->vir_width, panel->vir_height);
380 return -EINVAL;
381 }
382
383 for (i = 0; i < part_hdr->logo_count; i++) {
384 struct grayscale_header *img_hdr = &hdr->img_hdr[i];
385 int pic_buf;
386 u32 offset = img_hdr->data_offset;
387 u32 size = img_hdr->data_size;
388 u32 logo_type = img_hdr->logo_type;
389
390 debug("offset=0x%x, size=%d,logo_type=%d,w=%d,h=%d\n",
391 offset, size, logo_type, img_hdr->w, img_hdr->h);
392
393 if (logo & logo_type) {
394 pic_buf = get_addr_by_type(dev, logo_type);
395
396 if (pic_buf <= 0) {
397 printf("Get buffer failed for image %d\n",
398 img_hdr->logo_type);
399 return -EIO;
400 }
401 if (!IS_ALIGNED((ulong)pic_buf,
402 ARCH_DMA_MINALIGN)) {
403 printf("disp buffer is not dma aligned\n");
404 return -EINVAL;
405 }
406 /*
407 * kernel logo is transmitted to kernel to display, and
408 * kernel will do the mirror operation, so skip kernel
409 * logo here.
410 */
411 if (panel->mirror && logo_type != EINK_LOGO_KERNEL) {
412 u32 w = panel->vir_width;
413 u32 h = panel->vir_height;
414 u32 mirror_buf = 0;
415
416 mirror_buf = get_addr_by_type(dev,
417 EINK_LOGO_UNMIRROR_TEMP_BUF);
418 if (mirror_buf <= 0) {
419 printf("get mirror buffer failed\n");
420 return -EIO;
421 }
422 read_grayscale(dev_desc, &part, offset, size,
423 (void *)((ulong)mirror_buf));
424 image_mirror((u8 *)((ulong)mirror_buf),
425 (u8 *)((ulong)pic_buf), w, h);
426 } else if (panel->rearrange && logo_type != EINK_LOGO_KERNEL) {
427 u32 w = panel->vir_width;
428 u32 h = panel->vir_height;
429 u32 rearrange_buf = 0;
430
431 rearrange_buf = get_addr_by_type(dev,
432 EINK_LOGO_UNMIRROR_TEMP_BUF);
433 if (rearrange_buf <= 0) {
434 printf("get mirror buffer failed\n");
435 return -EIO;
436 }
437 read_grayscale(dev_desc, &part, offset, size,
438 (void *)((ulong)rearrange_buf));
439 image_rearrange((u8 *)((ulong)rearrange_buf),
440 (u8 *)((ulong)pic_buf), w, h);
441 } else {
442 read_grayscale(dev_desc, &part, offset, size,
443 (void *)((ulong)pic_buf));
444 }
445 flush_dcache_range((ulong)pic_buf,
446 ALIGN((ulong)pic_buf + size,
447 CONFIG_SYS_CACHELINE_SIZE));
448 *loaded_logo |= logo_type;
449
450 logo &= ~logo_type;
451 if (!logo)
452 break;
453 }
454 }
455
456 return 0;
457 }
458
ebc_power_set(struct udevice * dev,int is_on)459 static int ebc_power_set(struct udevice *dev, int is_on)
460 {
461 int ret;
462 struct rockchip_eink_display_priv *priv = dev_get_priv(dev);
463 struct ebc_panel *panel = dev_get_platdata(dev);
464 struct udevice *ebc_tcon_dev = priv->ebc_tcon_dev;
465 struct rk_ebc_tcon_ops *ebc_tcon_ops = ebc_tcon_get_ops(ebc_tcon_dev);
466 struct udevice *ebc_pwr_dev = priv->ebc_pwr_dev;
467 struct rk_ebc_pwr_ops *pwr_ops = ebc_pwr_get_ops(ebc_pwr_dev);
468
469 if (is_on) {
470 ret = pwr_ops->power_on(ebc_pwr_dev);
471 if (ret) {
472 printf("%s, power on failed\n", __func__);
473 return -1;
474 }
475 ret = ebc_tcon_ops->enable(ebc_tcon_dev, panel);
476 if (ret) {
477 printf("%s, ebc tcon enabled failed\n", __func__);
478 return -1;
479 }
480 } else {
481 ret = ebc_tcon_ops->disable(ebc_tcon_dev);
482 if (ret) {
483 printf("%s, ebc tcon disable failed\n", __func__);
484 return -1;
485 }
486 ret = pwr_ops->power_down(ebc_pwr_dev);
487 if (ret) {
488 printf("%s, power_down failed\n", __func__);
489 return -1;
490 }
491 }
492 return 0;
493 }
494
eink_display(struct udevice * dev,u32 pre_img_buf,u32 cur_img_buf,u32 lut_type,int update_mode)495 static int eink_display(struct udevice *dev, u32 pre_img_buf,
496 u32 cur_img_buf, u32 lut_type, int update_mode)
497 {
498 u32 temperature, frame_num;
499 struct rockchip_eink_display_priv *priv = dev_get_priv(dev);
500 struct ebc_panel *plat = dev_get_platdata(dev);
501 struct epd_lut_ops *lut_ops = &plat->lut_ops;
502 struct udevice *ebc_pwr_dev = priv->ebc_pwr_dev;
503 struct rk_ebc_pwr_ops *pwr_ops = ebc_pwr_get_ops(ebc_pwr_dev);
504 struct udevice *ebc_tcon_dev = priv->ebc_tcon_dev;
505 struct rk_ebc_tcon_ops *ebc_tcon_ops = ebc_tcon_get_ops(ebc_tcon_dev);
506
507 pwr_ops->temp_get(ebc_pwr_dev, &temperature);
508 if (temperature <= 0 || temperature > 50) {
509 printf("temperature = %d, out of range0~50 ,use 25\n",
510 temperature);
511 temperature = 25;
512 }
513
514 if (!lut_ops->lut_get) {
515 printf("get lut ops failed\n");
516 return -EIO;
517 }
518 lut_ops->lut_get(&plat->lut_data, lut_type, temperature);
519 frame_num = plat->lut_data.frame_num;
520 debug("lut_type=%d, frame num=%d, temp=%d\n", lut_type,
521 frame_num, temperature);
522
523 ebc_tcon_ops->wait_for_last_frame_complete(ebc_tcon_dev);
524 ebc_tcon_ops->lut_data_set(ebc_tcon_dev, plat->lut_data.data,
525 frame_num, 0);
526 ebc_tcon_ops->dsp_mode_set(ebc_tcon_dev, update_mode,
527 LUT_MODE, !THREE_WIN_MODE, !EINK_MODE);
528 ebc_tcon_ops->image_addr_set(ebc_tcon_dev, pre_img_buf, cur_img_buf);
529 ebc_tcon_ops->frame_start(ebc_tcon_dev, frame_num);
530 return 0;
531 }
532
rk_eink_display_init(void)533 static int rk_eink_display_init(void)
534 {
535 int ret;
536 struct uclass *uc;
537 struct udevice *dev;
538
539 if (eink_dev) {
540 printf("ebc-dev is already initialized!\n");
541 return 0;
542 }
543
544 ret = uclass_get(UCLASS_EINK_DISPLAY, &uc);
545 if (ret) {
546 printf("can't find uclass eink\n");
547 return -ENODEV;
548 }
549 for (uclass_first_device(UCLASS_EINK_DISPLAY, &dev);
550 dev; uclass_next_device(&dev))
551 ;
552
553 if (eink_dev) {
554 printf("ebc-dev is probed success!\n");
555 return 0;
556 }
557 printf("Can't find ebc-dev\n");
558 return -ENODEV;
559 }
560
561 /*
562 * Eink display need current and previous image buffer, We assume
563 * every type of logo has only one image, so just tell this function
564 * last logo type and current logo type, it will find the right images.
565 * last_logo_type: -1 means it's first displaying.
566 */
rockchip_eink_show_logo(int cur_logo_type,int update_mode)567 static int rockchip_eink_show_logo(int cur_logo_type, int update_mode)
568 {
569 int ret = 0;
570 u32 logo_addr;
571 u32 last_logo_addr;
572 struct ebc_panel *plat;
573 struct udevice *dev;
574 static u32 loaded_logo = 0;
575 struct rockchip_eink_display_priv *priv;
576
577 if (!eink_dev) {
578 static bool first_init = true;
579
580 if (first_init) {
581 first_init = false;
582 ret = rk_eink_display_init();
583 if (ret) {
584 printf("Get ebc dev failed, check dts\n");
585 return -ENODEV;
586 }
587 } else {
588 return -ENODEV;
589 }
590 }
591 dev = eink_dev;
592
593 /*Don't need to update display*/
594 if (last_logo_type == cur_logo_type) {
595 debug("Same as last picture, Don't need to display\n");
596 return 0;
597 }
598
599 plat = dev_get_platdata(dev);
600 priv = dev_get_priv(dev);
601
602 /*
603 * The last_logo_type is -1 means it's first displaying
604 */
605 if (last_logo_type == -1) {
606 ret = ebc_power_set(dev, EBC_PWR_ON);
607 if (ret) {
608 printf("Eink power on failed\n");
609 return -1;
610 }
611
612 int size = (plat->vir_width * plat->vir_height) >> 1;
613
614 logo_addr = get_addr_by_type(dev, EINK_LOGO_RESET);
615 memset((u32 *)(u64)logo_addr, 0xff, size);
616 flush_dcache_range((ulong)logo_addr,
617 ALIGN((ulong)logo_addr + size,
618 CONFIG_SYS_CACHELINE_SIZE));
619 eink_display(dev, logo_addr, logo_addr,
620 WF_TYPE_RESET, EINK_LOGO_RESET);
621 last_logo_type = 0;
622 last_logo_addr = logo_addr;
623 } else {
624 last_logo_addr = get_addr_by_type(dev, last_logo_type);
625 if (last_logo_addr < 0) {
626 printf("Invalid last logo addr, exit!\n");
627 goto out;
628 }
629 }
630 ret = read_needed_logo_from_partition(dev, cur_logo_type,
631 &loaded_logo);
632 if (ret || !(loaded_logo & cur_logo_type)) {
633 printf("read logo[0x%x] failed, loaded_logo=0x%x\n",
634 cur_logo_type, loaded_logo);
635 ret = -EIO;
636 goto out;
637 }
638 logo_addr = get_addr_by_type(dev, cur_logo_type);
639 debug("logo_addr=%x, logo_type=%d\n", logo_addr, cur_logo_type);
640 if (logo_addr <= 0) {
641 printf("get logo buffer failed\n");
642 ret = -EIO;
643 goto out;
644 }
645
646 eink_display(dev, last_logo_addr, logo_addr, WF_TYPE_GC16, update_mode);
647
648 if (priv->backlight)
649 backlight_enable(priv->backlight);
650
651 last_logo_type = cur_logo_type;
652
653 if (cur_logo_type == EINK_LOGO_POWEROFF) {
654 struct udevice *ebc_tcon_dev = priv->ebc_tcon_dev;
655 struct rk_ebc_tcon_ops *ebc_tcon_ops;
656
657 last_logo_type = -1;
658 /*
659 * For normal logo display, waiting for the last frame
660 * completion before start a new frame, except one
661 * situation which charging logo display finished,
662 * because device will rebooting or shutdown after
663 * charging logo is competed.
664 *
665 * We should take care of the power sequence,
666 * because ebc can't power off if last frame
667 * data is still sending, so keep the ebc power
668 * during u-boot phase and shutdown the
669 * power only if uboot charging is finished.
670 */
671 ebc_tcon_ops = ebc_tcon_get_ops(ebc_tcon_dev);
672 ebc_tcon_ops->wait_for_last_frame_complete(ebc_tcon_dev);
673 debug("charging logo displaying is complete\n");
674 /*
675 *shutdown ebc after charging logo display is complete
676 */
677 ret = ebc_power_set(dev, EBC_PWR_DOWN);
678 if (ret)
679 printf("Eink power down failed\n");
680 goto out;
681 }
682
683 /*
684 * System will boot up to kernel only when the
685 * logo is uboot logo
686 */
687 if (cur_logo_type == EINK_LOGO_UBOOT) {
688 char logo_args[64] = {0};
689 u32 uboot_logo_buf;
690
691 if (plat->mirror || plat->rearrange)
692 uboot_logo_buf = get_addr_by_type(dev,
693 EINK_LOGO_UNMIRROR_TEMP_BUF);
694 else
695 uboot_logo_buf = logo_addr;
696 printf("Transmit uboot logo addr(0x%x) to kernel\n",
697 uboot_logo_buf);
698 sprintf(logo_args, "ulogo_addr=0x%x", uboot_logo_buf);
699 env_update("bootargs", logo_args);
700 ret = read_needed_logo_from_partition(dev, EINK_LOGO_KERNEL,
701 &loaded_logo);
702 if (ret || !(loaded_logo & EINK_LOGO_KERNEL)) {
703 printf("No invalid kernel logo in logo.img\n");
704 } else {
705 int klogo_addr = get_addr_by_type(dev,
706 EINK_LOGO_KERNEL);
707
708 if (klogo_addr <= 0) {
709 printf("get kernel logo buffer failed\n");
710 ret = -EIO;
711 goto out;
712 }
713 printf("Transmit kernel logo addr(0x%x) to kernel\n",
714 klogo_addr);
715 sprintf(logo_args, "klogo_addr=0x%x", klogo_addr);
716 env_update("bootargs", logo_args);
717 }
718 }
719
720 out:
721 return ret;
722 }
723
rockchip_eink_show_uboot_logo(void)724 int rockchip_eink_show_uboot_logo(void)
725 {
726 return rockchip_eink_show_logo(EINK_LOGO_UBOOT, EINK_UPDATE_DIFF);
727 }
728
rockchip_eink_show_charge_logo(int logo_type)729 int rockchip_eink_show_charge_logo(int logo_type)
730 {
731 return rockchip_eink_show_logo(logo_type, EINK_UPDATE_DIFF);
732 }
733
rockchip_eink_display_probe(struct udevice * dev)734 static int rockchip_eink_display_probe(struct udevice *dev)
735 {
736 int ret, vcom, size, i;
737 const fdt32_t *list;
738 uint32_t phandle;
739 struct rockchip_eink_display_priv *priv = dev_get_priv(dev);
740
741 /* Before relocation we don't need to do anything */
742 if (!(gd->flags & GD_FLG_RELOC))
743 return 0;
744
745 ret = uclass_get_device_by_phandle(UCLASS_EBC, dev,
746 "ebc_tcon",
747 &priv->ebc_tcon_dev);
748 if (ret) {
749 dev_err(dev, "Cannot get ebc_tcon: %d\n", ret);
750 return ret;
751 }
752
753 list = dev_read_prop(dev, "pmic", &size);
754 if (!list) {
755 dev_err(dev, "Cannot get pmic prop\n");
756 return -EINVAL;
757 }
758
759 size /= sizeof(*list);
760 for (i = 0; i < size; i++) {
761 phandle = fdt32_to_cpu(*list++);
762 ret = uclass_get_device_by_phandle_id(UCLASS_I2C_GENERIC,
763 phandle,
764 &priv->ebc_pwr_dev);
765 if (!ret) {
766 printf("Eink: use pmic %s\n", priv->ebc_pwr_dev->name);
767 break;
768 }
769 }
770 if (ret) {
771 dev_err(dev, "Cannot get pmic: %d\n", ret);
772 return ret;
773 }
774
775 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev,
776 "backlight", &priv->backlight);
777 if (ret && ret != -ENOENT) {
778 printf("%s: Cannot get backlight: %d\n", __func__, ret);
779 }
780
781 vcom = read_vcom_from_vendor();
782 if (vcom <= 0) {
783 printf("read vcom from vendor failed, use default vcom\n");
784 priv->vcom = VCOM_DEFAULT_VALUE;
785 } else {
786 priv->vcom = vcom;
787 }
788
789 if (priv->ebc_pwr_dev) {
790 struct rk_ebc_pwr_ops *pwr_ops;
791
792 pwr_ops = ebc_pwr_get_ops(priv->ebc_pwr_dev);
793 ret = pwr_ops->vcom_set(priv->ebc_pwr_dev, priv->vcom);
794 if (ret) {
795 printf("%s, vcom_set failed\n", __func__);
796 return -EIO;
797 }
798 }
799
800 // read lut to ram, and get lut ops
801 ret = read_waveform(dev);
802 if (ret < 0) {
803 printf("read wavform failed\n");
804 return -EIO;
805 }
806
807 eink_dev = dev;
808
809 return 0;
810 }
811
rockchip_eink_display_ofdata_to_platdata(struct udevice * dev)812 static int rockchip_eink_display_ofdata_to_platdata(struct udevice *dev)
813 {
814 fdt_size_t size;
815 fdt_addr_t tmp_addr;
816 struct device_node *disp_mem;
817 struct device_node *waveform_mem;
818 struct ebc_panel *plat = dev_get_platdata(dev);
819
820 plat->width = dev_read_u32_default(dev, "panel,width", 0);
821 plat->height = dev_read_u32_default(dev, "panel,height", 0);
822 plat->vir_width = dev_read_u32_default(dev, "panel,vir_width", plat->width);
823 plat->vir_height = dev_read_u32_default(dev, "panel,vir_height", plat->height);
824 plat->sdck = dev_read_u32_default(dev, "panel,sdck", 0);
825 plat->lsl = dev_read_u32_default(dev, "panel,lsl", 0);
826 plat->lbl = dev_read_u32_default(dev, "panel,lbl", 0);
827 plat->ldl = dev_read_u32_default(dev, "panel,ldl", 0);
828 plat->lel = dev_read_u32_default(dev, "panel,lel", 0);
829 plat->gdck_sta = dev_read_u32_default(dev, "panel,gdck-sta", 0);
830 plat->lgonl = dev_read_u32_default(dev, "panel,lgonl", 0);
831 plat->fsl = dev_read_u32_default(dev, "panel,fsl", 0);
832 plat->fbl = dev_read_u32_default(dev, "panel,fbl", 0);
833 plat->fdl = dev_read_u32_default(dev, "panel,fdl", 0);
834 plat->fel = dev_read_u32_default(dev, "panel,fel", 0);
835 plat->panel_16bit = dev_read_u32_default(dev, "panel,panel_16bit", 0);
836 plat->panel_color = dev_read_u32_default(dev, "panel,panel_color", 0);
837 plat->mirror = dev_read_u32_default(dev, "panel,mirror", 0);
838 plat->rearrange = dev_read_u32_default(dev, "panel,rearrange", 0);
839 plat->width_mm = dev_read_u32_default(dev, "panel,width-mm", 0);
840 plat->height_mm = dev_read_u32_default(dev, "panel,height-mm", 0);
841
842 disp_mem = of_parse_phandle(ofnode_to_np(dev_ofnode(dev)),
843 "memory-region", 0);
844 if (!disp_mem) {
845 dev_err(dev, "Cannot get memory-region from dts\n");
846 return -ENODEV;
847 }
848 tmp_addr = ofnode_get_addr_size(np_to_ofnode(disp_mem), "reg", &size);
849 if (tmp_addr == FDT_ADDR_T_NONE) {
850 printf("get display memory address failed\n");
851 return -ENODEV;
852 }
853
854 plat->disp_pbuf = (u64)map_sysmem(tmp_addr, 0);
855 plat->disp_pbuf_size = size;
856 debug("display mem=0x%x, size=%x\n", plat->disp_pbuf,
857 plat->disp_pbuf_size);
858 waveform_mem = of_parse_phandle(ofnode_to_np(dev_ofnode(dev)),
859 "waveform-region", 0);
860 if (!waveform_mem) {
861 printf("Cannot get waveform-region from dts\n");
862 return -ENODEV;
863 }
864 tmp_addr = ofnode_get_addr_size(np_to_ofnode(waveform_mem),
865 "reg", &size);
866 if (tmp_addr == FDT_ADDR_T_NONE) {
867 printf("get waveform memory address failed\n");
868 return -ENODEV;
869 }
870
871 plat->lut_pbuf = map_sysmem(tmp_addr, 0);
872 plat->lut_pbuf_size = size;
873 debug("lut mem=0x%p, size=%x\n", plat->lut_pbuf, plat->lut_pbuf_size);
874 return 0;
875 }
876
877 static const struct udevice_id rockchip_eink_display_ids[] = {
878 { .compatible = "rockchip,ebc-dev", },
879 {}
880 };
881
882 U_BOOT_DRIVER(rk_eink_display) = {
883 .name = "rockchip_eink_display",
884 .id = UCLASS_EINK_DISPLAY,
885 .of_match = rockchip_eink_display_ids,
886 .ofdata_to_platdata = rockchip_eink_display_ofdata_to_platdata,
887 .probe = rockchip_eink_display_probe,
888 .priv_auto_alloc_size = sizeof(struct rockchip_eink_display_priv),
889 .platdata_auto_alloc_size = sizeof(struct ebc_panel),
890 };
891
892 UCLASS_DRIVER(rk_eink) = {
893 .id = UCLASS_EINK_DISPLAY,
894 .name = "rk_eink",
895 };
896
897