blob: 266e22070a6ab0627ab8175ab66ea0eb79161614 [file] [log] [blame]
Dima Zavind5b0b6a2009-01-15 18:09:25 -08001/*
2 * Copyright (c) 2008, Google Inc.
3 * All rights reserved.
4 *
Channagoud Kadabi7af9fbc2015-02-13 20:09:55 -08005 * Copyright (c) 2009-2015, The Linux Foundation. All rights reserved.
Shashank Mittal4f99a882010-02-01 13:58:50 -08006 *
Dima Zavind5b0b6a2009-01-15 18:09:25 -08007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <debug.h>
32#include <err.h>
33#include <stdlib.h>
34#include <dev/fbcon.h>
Chandan Uddaraju40b227d2010-08-03 19:25:41 -070035#include <splash.h>
Greg Griscod6250552011-06-29 14:40:23 -070036#include <platform.h>
37#include <string.h>
Channagoud Kadabi7af9fbc2015-02-13 20:09:55 -080038#include <arch/ops.h>
Dima Zavind5b0b6a2009-01-15 18:09:25 -080039
40#include "font5x12.h"
41
42struct pos {
43 int x;
44 int y;
45};
46
47static struct fbcon_config *config = NULL;
48
Chandan Uddaraju2943fd62010-06-21 10:56:39 -070049#define RGB565_BLACK 0x0000
Dima Zavind5b0b6a2009-01-15 18:09:25 -080050#define RGB565_WHITE 0xffff
51
Chandan Uddaraju78ae6752010-10-19 12:57:10 -070052#define RGB888_BLACK 0x000000
53#define RGB888_WHITE 0xffffff
54
Dima Zavind5b0b6a2009-01-15 18:09:25 -080055#define FONT_WIDTH 5
56#define FONT_HEIGHT 12
57
58static uint16_t BGCOLOR;
59static uint16_t FGCOLOR;
60
61static struct pos cur_pos;
62static struct pos max_pos;
63
64static void fbcon_drawglyph(uint16_t *pixels, uint16_t paint, unsigned stride,
65 unsigned *glyph)
66{
67 unsigned x, y, data;
68 stride -= FONT_WIDTH;
69
70 data = glyph[0];
71 for (y = 0; y < (FONT_HEIGHT / 2); ++y) {
72 for (x = 0; x < FONT_WIDTH; ++x) {
73 if (data & 1)
74 *pixels = paint;
75 data >>= 1;
76 pixels++;
77 }
78 pixels += stride;
79 }
80
81 data = glyph[1];
82 for (y = 0; y < (FONT_HEIGHT / 2); y++) {
83 for (x = 0; x < FONT_WIDTH; x++) {
84 if (data & 1)
85 *pixels = paint;
86 data >>= 1;
87 pixels++;
88 }
89 pixels += stride;
90 }
91}
92
Dima Zavin25ed9942009-01-28 17:04:19 -080093static void fbcon_flush(void)
94{
Mao Flynn7b379f32015-04-20 00:28:30 +080095 unsigned total_x, total_y;
96 unsigned bytes_per_bpp;
97
Dima Zavin25ed9942009-01-28 17:04:19 -080098 if (config->update_start)
99 config->update_start();
100 if (config->update_done)
101 while (!config->update_done());
Mao Flynn7b379f32015-04-20 00:28:30 +0800102
103 total_x = config->width;
104 total_y = config->height;
105 bytes_per_bpp = ((config->bpp) / 8);
106 arch_clean_invalidate_cache_range((addr_t) config->base, (total_x * total_y * bytes_per_bpp));
Dima Zavin25ed9942009-01-28 17:04:19 -0800107}
108
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800109/* TODO: Take stride into account */
110static void fbcon_scroll_up(void)
111{
112 unsigned short *dst = config->base;
113 unsigned short *src = dst + (config->width * FONT_HEIGHT);
114 unsigned count = config->width * (config->height - FONT_HEIGHT);
115
116 while(count--) {
117 *dst++ = *src++;
118 }
119
120 count = config->width * FONT_HEIGHT;
121 while(count--) {
122 *dst++ = BGCOLOR;
123 }
Dima Zavin25ed9942009-01-28 17:04:19 -0800124
125 fbcon_flush();
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800126}
127
128/* TODO: take stride into account */
Shashank Mittal4f99a882010-02-01 13:58:50 -0800129void fbcon_clear(void)
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800130{
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800131 unsigned count = config->width * config->height;
Chandan Uddaraju40b227d2010-08-03 19:25:41 -0700132 memset(config->base, BGCOLOR, count * ((config->bpp) / 8));
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800133}
134
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800135
136static void fbcon_set_colors(unsigned bg, unsigned fg)
137{
138 BGCOLOR = bg;
139 FGCOLOR = fg;
140}
141
142void fbcon_putc(char c)
143{
144 uint16_t *pixels;
145
146 /* ignore anything that happens before fbcon is initialized */
147 if (!config)
148 return;
149
150 if((unsigned char)c > 127)
151 return;
152 if((unsigned char)c < 32) {
153 if(c == '\n')
154 goto newline;
155 else if (c == '\r')
156 cur_pos.x = 0;
157 return;
158 }
159
160 pixels = config->base;
161 pixels += cur_pos.y * FONT_HEIGHT * config->width;
162 pixels += cur_pos.x * (FONT_WIDTH + 1);
163 fbcon_drawglyph(pixels, FGCOLOR, config->stride,
164 font5x12 + (c - 32) * 2);
165
166 cur_pos.x++;
167 if (cur_pos.x < max_pos.x)
168 return;
169
170newline:
171 cur_pos.y++;
172 cur_pos.x = 0;
173 if(cur_pos.y >= max_pos.y) {
174 cur_pos.y = max_pos.y - 1;
175 fbcon_scroll_up();
Dima Zavin25ed9942009-01-28 17:04:19 -0800176 } else
177 fbcon_flush();
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800178}
179
180void fbcon_setup(struct fbcon_config *_config)
181{
182 uint32_t bg;
183 uint32_t fg;
184
185 ASSERT(_config);
186
187 config = _config;
188
189 switch (config->format) {
190 case FB_FORMAT_RGB565:
Shashank Mittalc648e712010-10-06 18:37:42 -0700191 fg = RGB565_WHITE;
192 bg = RGB565_BLACK;
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800193 break;
Mao Flynn7b379f32015-04-20 00:28:30 +0800194 case FB_FORMAT_RGB888:
195 fg = RGB888_WHITE;
196 bg = RGB888_BLACK;
197 break;
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800198 default:
199 dprintf(CRITICAL, "unknown framebuffer pixel format\n");
200 ASSERT(0);
201 break;
202 }
203
204 fbcon_set_colors(bg, fg);
205
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800206 cur_pos.x = 0;
207 cur_pos.y = 0;
208 max_pos.x = config->width / (FONT_WIDTH+1);
209 max_pos.y = (config->height - 1) / FONT_HEIGHT;
Shashank Mittal37040832010-08-24 15:57:57 -0700210#if !DISPLAY_SPLASH_SCREEN
211 fbcon_clear();
212#endif
Dima Zavind5b0b6a2009-01-15 18:09:25 -0800213}
Shashank Mittal4f99a882010-02-01 13:58:50 -0800214
215struct fbcon_config* fbcon_display(void)
216{
Mao Flynn7b379f32015-04-20 00:28:30 +0800217 return config;
Shashank Mittal4f99a882010-02-01 13:58:50 -0800218}
Chandan Uddaraju40b227d2010-08-03 19:25:41 -0700219
Mao Flynn7b379f32015-04-20 00:28:30 +0800220void fbcon_extract_to_screen(logo_img_header *header, void* address)
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530221{
Mao Flynn7b379f32015-04-20 00:28:30 +0800222 const uint8_t *imagestart = (const uint8_t *)address;
223 uint pos = 0, offset;
224 uint count = 0;
225 uint x = 0, y = 0;
226 uint8_t *base, *p;
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530227
Mao Flynn7b379f32015-04-20 00:28:30 +0800228 if (!config || header->width > config->width
229 || header->height > config->height) {
230 dprintf(INFO, "the logo img is too large\n");
231 return;
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530232 }
233
Mao Flynn7b379f32015-04-20 00:28:30 +0800234 base = (uint8_t *) config->base;
235
236 /* put the logo to be center */
237 offset = (config->height - header->height) / 2;
238 if (offset)
239 base += (offset * config->width) * 3;
240 offset = (config->width - header->width ) / 2;
241
242 x = offset;
243 while (count < (uint)header->height * (uint)header->width) {
244 uint8_t run = *(imagestart + pos);
245 bool repeat_run = (run & 0x80);
246 uint runlen = (run & 0x7f) + 1;
247 uint runpos;
248
249 /* consume the run byte */
250 pos++;
251
252 p = base + (y * config->width + x) * 3;
253
254 /* start of a run */
255 for (runpos = 0; runpos < runlen; runpos++) {
256 *p++ = *(imagestart + pos);
257 *p++ = *(imagestart + pos + 1);
258 *p++ = *(imagestart + pos + 2);
259 count++;
260
261 x++;
262
263 /* if a run of raw pixels, consume an input pixel */
264 if (!repeat_run)
265 pos += 3;
266 }
267
268 /* if this was a run of repeated pixels, consume the one input pixel we repeated */
269 if (repeat_run)
270 pos += 3;
271
272 /* the generator will keep compressing data line by line */
273 /* don't cross the lines */
274 if (x == header->width + offset) {
275 y++;
276 x = offset;
277 }
278 }
279
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530280}
281
Mao Flynn7b379f32015-04-20 00:28:30 +0800282void display_default_image_on_screen(void)
Chandan Uddaraju40b227d2010-08-03 19:25:41 -0700283{
Mao Flynn7b379f32015-04-20 00:28:30 +0800284 unsigned i = 0;
285 unsigned total_x;
286 unsigned total_y;
287 unsigned bytes_per_bpp;
288 unsigned image_base;
Channagoud Kadabi956cf502012-03-08 03:49:50 +0530289
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530290 if (!config) {
291 dprintf(CRITICAL,"NULL configuration, image cannot be displayed\n");
292 return;
293 }
Chandan Uddaraju78ae6752010-10-19 12:57:10 -0700294
Mao Flynn7b379f32015-04-20 00:28:30 +0800295 fbcon_clear(); // clear screen with Black color
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530296
297 total_x = config->width;
298 total_y = config->height;
299 bytes_per_bpp = ((config->bpp) / 8);
Mao Flynn7b379f32015-04-20 00:28:30 +0800300 image_base = ((((total_y/2) - (SPLASH_IMAGE_HEIGHT / 2) - 1) *
301 (config->width)) + (total_x/2 - (SPLASH_IMAGE_WIDTH / 2)));
Channagoud Kadabi956cf502012-03-08 03:49:50 +0530302
Chandan Uddaraju78ae6752010-10-19 12:57:10 -0700303#if DISPLAY_TYPE_MIPI
Mao Flynn7b379f32015-04-20 00:28:30 +0800304 if (bytes_per_bpp == 3) {
305 for (i = 0; i < SPLASH_IMAGE_HEIGHT; i++) {
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530306 memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
Mao Flynn7b379f32015-04-20 00:28:30 +0800307 imageBuffer_rgb888 + (i * SPLASH_IMAGE_WIDTH * bytes_per_bpp),
308 SPLASH_IMAGE_WIDTH * bytes_per_bpp);
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530309 }
Chandan Uddaraju78ae6752010-10-19 12:57:10 -0700310 }
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530311 fbcon_flush();
Kinson Chike5c93432011-06-17 09:10:29 -0700312#if DISPLAY_MIPI_PANEL_NOVATEK_BLUE
Aparna Mallavarapuce06a012013-09-06 23:03:24 +0530313 if(is_cmd_mode_enabled())
Mao Flynn7b379f32015-04-20 00:28:30 +0800314 mipi_dsi_cmd_mode_trigger();
Kinson Chike5c93432011-06-17 09:10:29 -0700315#endif
Chandan Uddarajufe93e822010-11-21 20:44:47 -0800316
Chandan Uddaraju78ae6752010-10-19 12:57:10 -0700317#else
Zohaib Alam03708752014-10-23 17:51:57 -0400318
Mao Flynn7b379f32015-04-20 00:28:30 +0800319 if (bytes_per_bpp == 2) {
320 for (i = 0; i < SPLASH_IMAGE_HEIGHT; i++) {
321 memcpy (config->base + ((image_base + (i * (config->width))) * bytes_per_bpp),
322 imageBuffer + (i * SPLASH_IMAGE_WIDTH * bytes_per_bpp),
323 SPLASH_IMAGE_WIDTH * bytes_per_bpp);
Zohaib Alam03708752014-10-23 17:51:57 -0400324 }
325 }
326 fbcon_flush();
Chandan Uddarajufe93e822010-11-21 20:44:47 -0800327#endif
Chandan Uddaraju40b227d2010-08-03 19:25:41 -0700328}
Mao Flynn7b379f32015-04-20 00:28:30 +0800329
330
331void display_image_on_screen(void)
332{
333#if DISPLAY_TYPE_MIPI
334 int fetch_image_from_partition();
335
336 if (fetch_image_from_partition() < 0) {
337 display_default_image_on_screen();
338 } else {
339 /* data has been put into the right place */
340 fbcon_flush();
341 }
342#else
343 display_default_image_on_screen();
344#endif
345}