diff options
Diffstat (limited to 'system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch')
-rw-r--r-- | system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch | 756 |
1 files changed, 756 insertions, 0 deletions
diff --git a/system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch b/system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch new file mode 100644 index 0000000..db7110f --- /dev/null +++ b/system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch @@ -0,0 +1,756 @@ +From a99e4e5fea639e2d163071011c2b866dde1e848b Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +Date: Sat, 15 Sep 2012 03:53:03 +0200 +Subject: [PATCH] init: Support DRM/KMS to display the boot logo + +Change-Id: Ia42ef34a65f8aeebeedb947b2d7067154720f5d2 +Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> +--- + init/Android.mk | 2 +- + init/logo-drm.c | 379 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + init/logo-fb.c | 163 ++++++++++++++++++++++++ + init/logo.c | 163 ------------------------ + 4 files changed, 543 insertions(+), 164 deletions(-) + create mode 100644 init/logo-drm.c + create mode 100644 init/logo-fb.c + delete mode 100644 init/logo.c + +diff --git a/init/Android.mk b/init/Android.mk +index f3287a8..485fc7f 100644 +--- a/init/Android.mk ++++ b/init/Android.mk +@@ -10,7 +10,7 @@ LOCAL_SRC_FILES:= \ + property_service.c \ + util.c \ + parser.c \ +- logo.c \ ++ logo-drm.c \ + keychords.c \ + signal_handler.c \ + init_parser.c \ +diff --git a/init/logo-drm.c b/init/logo-drm.c +new file mode 100644 +index 0000000..22ecf08 +--- /dev/null ++++ b/init/logo-drm.c +@@ -0,0 +1,379 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include <stdbool.h> ++#include <stdio.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <fcntl.h> ++#include <sys/mman.h> ++#include <sys/stat.h> ++#include <sys/types.h> ++ ++#include <linux/kd.h> ++ ++#include <drm/drm.h> ++#include <drm/drm_mode.h> ++#include <drm/drm_fourcc.h> ++ ++#include "log.h" ++ ++#ifdef ANDROID ++#include <cutils/memory.h> ++#else ++void android_memset16(void *_ptr, unsigned short val, unsigned count) ++{ ++ unsigned short *ptr = _ptr; ++ count >>= 1; ++ while(count--) ++ *ptr++ = val; ++} ++#endif ++ ++struct drm { ++ int fd; ++ struct { ++ uint32_t crtc; ++ uint32_t connector; ++ struct drm_mode_modeinfo mode; ++ } kms; ++ struct { ++ unsigned int handle; ++ void *map; ++ size_t size; ++ size_t pitch; ++ } bo; ++ struct { ++ unsigned int id; ++ } fb; ++}; ++ ++#define U642VOID(x) ((void *)(unsigned long)(x)) ++#define VOID2U64(x) ((uint64_t)(unsigned long)(x)) ++ ++static void drm_close(struct drm *drm, bool destroy) ++{ ++ struct drm_mode_destroy_dumb dumb; ++ uint32_t id; ++ ++ if (drm->bo.map) ++ munmap(drm->bo.map, drm->bo.size); ++ ++ if (destroy) { ++ if (drm->fb.id) { ++ id = drm->fb.id; ++ ioctl(drm->fd, DRM_IOCTL_MODE_RMFB, &id); ++ } ++ ++ if (drm->bo.handle) { ++ memset(&dumb, 0, sizeof dumb); ++ dumb.handle = drm->bo.handle; ++ ioctl(drm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, dumb); ++ } ++ } ++ ++ close(drm->fd); ++} ++ ++static int drm_get_resources(struct drm *drm) ++{ ++ struct drm_mode_card_res counts; ++ struct drm_mode_card_res res; ++ int ret; ++ ++retry: ++ memset(&res, 0, sizeof res); ++ ret = ioctl(drm->fd, DRM_IOCTL_MODE_GETRESOURCES, &res); ++ if (ret < 0) ++ return -1; ++ ++ counts = res; ++ memset(&res, 0, sizeof res); ++ ++ if (counts.count_crtcs) { ++ res.count_crtcs = counts.count_crtcs; ++ res.crtc_id_ptr = VOID2U64(malloc(res.count_crtcs * ++ sizeof(uint32_t))); ++ if (!res.crtc_id_ptr) { ++ ret = -1; ++ goto done; ++ } ++ } ++ ++ if (counts.count_connectors) { ++ res.count_connectors = counts.count_connectors; ++ res.connector_id_ptr = VOID2U64(malloc(res.count_connectors * ++ sizeof(uint32_t))); ++ if (!res.connector_id_ptr) { ++ ret = -1; ++ goto done; ++ } ++ } ++ ++ ret = ioctl(drm->fd, DRM_IOCTL_MODE_GETRESOURCES, &res); ++ if (ret < 0) ++ goto done; ++ ++ /* The number of available connectors and etc may have changed with a ++ * hotplug event in between the ioctls, in which case the field is ++ * silently ignored by the kernel. ++ */ ++ if (counts.count_crtcs < res.count_crtcs || ++ counts.count_connectors < res.count_connectors) { ++ free(U642VOID(res.crtc_id_ptr)); ++ free(U642VOID(res.connector_id_ptr)); ++ goto retry; ++ } ++ ++ /* We need at least one CRTC and one connector. */ ++ if (res.count_crtcs == 0 || res.count_connectors == 0) { ++ ret = -1; ++ goto done; ++ } ++ ++ drm->kms.crtc = *(uint32_t *)U642VOID(res.crtc_id_ptr); ++ drm->kms.connector = *(uint32_t *)U642VOID(res.connector_id_ptr); ++ ++ ret = 0; ++ ++done: ++ free(U642VOID(res.crtc_id_ptr)); ++ free(U642VOID(res.connector_id_ptr)); ++ ++ return ret; ++} ++ ++static int drm_get_modes(struct drm *drm) ++{ ++ struct drm_mode_get_connector counts; ++ struct drm_mode_get_connector conn; ++ int ret; ++ ++retry: ++ memset(&conn, 0, sizeof conn); ++ conn.connector_id = drm->kms.connector; ++ ++ ret = ioctl(drm->fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn); ++ if (ret < 0) ++ return -1; ++ ++ counts = conn; ++ memset(&conn, 0, sizeof conn); ++ conn.connector_id = drm->kms.connector; ++ ++ if (counts.count_modes) { ++ conn.count_modes = counts.count_modes; ++ conn.modes_ptr = VOID2U64(malloc(conn.count_modes * ++ sizeof(struct drm_mode_modeinfo))); ++ if (!conn.modes_ptr) { ++ ret = -1; ++ goto done; ++ } ++ } ++ ++ ret = ioctl(drm->fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn); ++ if (ret < 0) ++ goto done; ++ ++ /* The number of available connectors and etc may have changed with a ++ * hotplug event in between the ioctls, in which case the field is ++ * silently ignored by the kernel. ++ */ ++ if (counts.count_modes < conn.count_modes) { ++ free(U642VOID(conn.modes_ptr)); ++ goto retry; ++ } ++ ++ /* We need at least one mode. */ ++ if (conn.count_modes == 0) { ++ ret = -1; ++ goto done; ++ } ++ ++ drm->kms.mode = *(struct drm_mode_modeinfo *)U642VOID(conn.modes_ptr); ++ ++ ret = 0; ++ ++done: ++ free(U642VOID(conn.modes_ptr)); ++ ++ return ret; ++} ++ ++static int drm_open(struct drm *drm) ++{ ++ struct drm_get_cap cap = { DRM_CAP_DUMB_BUFFER, 0 }; ++ struct drm_mode_create_dumb dumb; ++ struct drm_mode_map_dumb map; ++ struct drm_mode_fb_cmd2 fb; ++ void *mem; ++ int ret; ++ ++ drm->fd = open("/dev/dri/card0", O_RDWR); ++ if (drm->fd < 0) ++ return -1; ++ ++ /* Verify that the driver supports dumb buffers. */ ++ ret = ioctl(drm->fd, DRM_IOCTL_GET_CAP, &cap); ++ if (ret < 0) ++ goto error; ++ if (!cap.value) ++ goto error; ++ ++ ret = drm_get_resources(drm); ++ if (ret < 0) ++ goto error; ++ ++ ret = drm_get_modes(drm); ++ if (ret < 0) ++ goto error; ++ ++ /* Create a buffer and map it. */ ++ memset(&dumb, 0, sizeof dumb); ++ dumb.bpp = 16; ++ dumb.width = drm->kms.mode.hdisplay; ++ dumb.height = drm->kms.mode.vdisplay; ++ ++ ret = ioctl(drm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &dumb); ++ if (ret < 0) ++ goto error; ++ ++ drm->bo.handle = dumb.handle; ++ drm->bo.size = dumb.size; ++ drm->bo.pitch = dumb.pitch; ++ ++ memset(&map, 0, sizeof map); ++ map.handle = drm->bo.handle; ++ ++ ret = ioctl(drm->fd, DRM_IOCTL_MODE_MAP_DUMB, &map); ++ if (ret < 0) ++ goto error; ++ ++ mem = mmap(0, drm->bo.size, PROT_READ | PROT_WRITE, MAP_SHARED, drm->fd, ++ map.offset); ++ if (mem == MAP_FAILED) ++ goto error; ++ ++ drm->bo.map = mem; ++ ++ /* Create a frame buffer. */ ++ memset(&fb, 0, sizeof fb); ++ fb.width = drm->kms.mode.hdisplay; ++ fb.height = drm->kms.mode.vdisplay; ++ fb.pixel_format = DRM_FORMAT_RGB565; ++ fb.handles[0] = drm->bo.handle; ++ fb.pitches[0] = drm->bo.pitch; ++ ++ ret = ioctl (drm->fd, DRM_IOCTL_MODE_ADDFB2, &fb); ++ if (ret < 0) ++ goto error; ++ ++ drm->fb.id = fb.fb_id; ++ ++ return 0; ++ ++error: ++ drm_close(drm, true); ++ return -1; ++} ++ ++static void drm_update(struct drm *drm) ++{ ++ struct drm_mode_crtc crtc; ++ uint32_t connector = drm->kms.connector; ++ int ret; ++ ++ memset(&crtc, 0, sizeof crtc); ++ crtc.crtc_id = drm->kms.crtc; ++ crtc.fb_id = drm->fb.id; ++ crtc.set_connectors_ptr = VOID2U64(&connector); ++ crtc.count_connectors = 1; ++ crtc.mode = drm->kms.mode; ++ crtc.mode_valid = 1; ++ ++ ioctl(drm->fd, DRM_IOCTL_MODE_SETCRTC, &crtc); ++} ++ ++static int vt_set_mode(int graphics) ++{ ++ int fd, r; ++ fd = open("/dev/tty0", O_RDWR | O_SYNC); ++ if (fd < 0) ++ return -1; ++ r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT)); ++ close(fd); ++ return r; ++} ++ ++/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ ++ ++int load_565rle_image(char *fn) ++{ ++ struct drm drm; ++ struct stat s; ++ unsigned short *data, *bits, *ptr; ++ unsigned count, max; ++ int fd; ++ ++ if (vt_set_mode(1)) ++ return -1; ++ ++ fd = open(fn, O_RDONLY); ++ if (fd < 0) { ++ ERROR("cannot open '%s'\n", fn); ++ goto fail_restore_text; ++ } ++ ++ if (fstat(fd, &s) < 0) ++ goto fail_close_file; ++ ++ data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); ++ if (data == MAP_FAILED) ++ goto fail_close_file; ++ ++ if (drm_open(&drm)) ++ goto fail_unmap_data; ++ ++ max = drm.bo.size; ++ ptr = data; ++ count = s.st_size; ++ bits = drm.bo.map; ++ while (count > 3) { ++ unsigned n = ptr[0]; ++ if (n > max) ++ break; ++ android_memset16(bits, ptr[1], n << 1); ++ bits += n; ++ max -= n; ++ ptr += 2; ++ count -= 4; ++ } ++ ++ munmap(data, s.st_size); ++ drm_update(&drm); ++ drm_close(&drm, false); ++ close(fd); ++ unlink(fn); ++ return 0; ++ ++fail_unmap_data: ++ munmap(data, s.st_size); ++fail_close_file: ++ close(fd); ++fail_restore_text: ++ vt_set_mode(0); ++ return -1; ++} +diff --git a/init/logo-fb.c b/init/logo-fb.c +new file mode 100644 +index 0000000..614224c +--- /dev/null ++++ b/init/logo-fb.c +@@ -0,0 +1,163 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include <stdio.h> ++#include <stdlib.h> ++#include <unistd.h> ++#include <fcntl.h> ++#include <sys/mman.h> ++#include <sys/stat.h> ++#include <sys/types.h> ++ ++#include <linux/fb.h> ++#include <linux/kd.h> ++ ++#include "log.h" ++ ++#ifdef ANDROID ++#include <cutils/memory.h> ++#else ++void android_memset16(void *_ptr, unsigned short val, unsigned count) ++{ ++ unsigned short *ptr = _ptr; ++ count >>= 1; ++ while(count--) ++ *ptr++ = val; ++} ++#endif ++ ++struct FB { ++ unsigned short *bits; ++ unsigned size; ++ int fd; ++ struct fb_fix_screeninfo fi; ++ struct fb_var_screeninfo vi; ++}; ++ ++#define fb_width(fb) ((fb)->vi.xres) ++#define fb_height(fb) ((fb)->vi.yres) ++#define fb_size(fb) ((fb)->vi.xres * (fb)->vi.yres * 2) ++ ++static int fb_open(struct FB *fb) ++{ ++ fb->fd = open("/dev/graphics/fb0", O_RDWR); ++ if (fb->fd < 0) ++ return -1; ++ ++ if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) ++ goto fail; ++ if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) ++ goto fail; ++ ++ fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, ++ MAP_SHARED, fb->fd, 0); ++ if (fb->bits == MAP_FAILED) ++ goto fail; ++ ++ return 0; ++ ++fail: ++ close(fb->fd); ++ return -1; ++} ++ ++static void fb_close(struct FB *fb) ++{ ++ munmap(fb->bits, fb_size(fb)); ++ close(fb->fd); ++} ++ ++/* there's got to be a more portable way to do this ... */ ++static void fb_update(struct FB *fb) ++{ ++ fb->vi.yoffset = 1; ++ ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); ++ fb->vi.yoffset = 0; ++ ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); ++} ++ ++static int vt_set_mode(int graphics) ++{ ++ int fd, r; ++ fd = open("/dev/tty0", O_RDWR | O_SYNC); ++ if (fd < 0) ++ return -1; ++ r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT)); ++ close(fd); ++ return r; ++} ++ ++/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ ++ ++int load_565rle_image(char *fn) ++{ ++ struct FB fb; ++ struct stat s; ++ unsigned short *data, *bits, *ptr; ++ unsigned count, max; ++ int fd; ++ ++ if (vt_set_mode(1)) ++ return -1; ++ ++ fd = open(fn, O_RDONLY); ++ if (fd < 0) { ++ ERROR("cannot open '%s'\n", fn); ++ goto fail_restore_text; ++ } ++ ++ if (fstat(fd, &s) < 0) { ++ goto fail_close_file; ++ } ++ ++ data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); ++ if (data == MAP_FAILED) ++ goto fail_close_file; ++ ++ if (fb_open(&fb)) ++ goto fail_unmap_data; ++ ++ max = fb_width(&fb) * fb_height(&fb); ++ ptr = data; ++ count = s.st_size; ++ bits = fb.bits; ++ while (count > 3) { ++ unsigned n = ptr[0]; ++ if (n > max) ++ break; ++ android_memset16(bits, ptr[1], n << 1); ++ bits += n; ++ max -= n; ++ ptr += 2; ++ count -= 4; ++ } ++ ++ munmap(data, s.st_size); ++ fb_update(&fb); ++ fb_close(&fb); ++ close(fd); ++ unlink(fn); ++ return 0; ++ ++fail_unmap_data: ++ munmap(data, s.st_size); ++fail_close_file: ++ close(fd); ++fail_restore_text: ++ vt_set_mode(0); ++ return -1; ++} ++ +diff --git a/init/logo.c b/init/logo.c +deleted file mode 100644 +index 614224c..0000000 +--- a/init/logo.c ++++ /dev/null +@@ -1,163 +0,0 @@ +-/* +- * Copyright (C) 2008 The Android Open Source Project +- * +- * Licensed under the Apache License, Version 2.0 (the "License"); +- * you may not use this file except in compliance with the License. +- * You may obtain a copy of the License at +- * +- * http://www.apache.org/licenses/LICENSE-2.0 +- * +- * Unless required by applicable law or agreed to in writing, software +- * distributed under the License is distributed on an "AS IS" BASIS, +- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- * See the License for the specific language governing permissions and +- * limitations under the License. +- */ +- +-#include <stdio.h> +-#include <stdlib.h> +-#include <unistd.h> +-#include <fcntl.h> +-#include <sys/mman.h> +-#include <sys/stat.h> +-#include <sys/types.h> +- +-#include <linux/fb.h> +-#include <linux/kd.h> +- +-#include "log.h" +- +-#ifdef ANDROID +-#include <cutils/memory.h> +-#else +-void android_memset16(void *_ptr, unsigned short val, unsigned count) +-{ +- unsigned short *ptr = _ptr; +- count >>= 1; +- while(count--) +- *ptr++ = val; +-} +-#endif +- +-struct FB { +- unsigned short *bits; +- unsigned size; +- int fd; +- struct fb_fix_screeninfo fi; +- struct fb_var_screeninfo vi; +-}; +- +-#define fb_width(fb) ((fb)->vi.xres) +-#define fb_height(fb) ((fb)->vi.yres) +-#define fb_size(fb) ((fb)->vi.xres * (fb)->vi.yres * 2) +- +-static int fb_open(struct FB *fb) +-{ +- fb->fd = open("/dev/graphics/fb0", O_RDWR); +- if (fb->fd < 0) +- return -1; +- +- if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) +- goto fail; +- if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) +- goto fail; +- +- fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, +- MAP_SHARED, fb->fd, 0); +- if (fb->bits == MAP_FAILED) +- goto fail; +- +- return 0; +- +-fail: +- close(fb->fd); +- return -1; +-} +- +-static void fb_close(struct FB *fb) +-{ +- munmap(fb->bits, fb_size(fb)); +- close(fb->fd); +-} +- +-/* there's got to be a more portable way to do this ... */ +-static void fb_update(struct FB *fb) +-{ +- fb->vi.yoffset = 1; +- ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); +- fb->vi.yoffset = 0; +- ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi); +-} +- +-static int vt_set_mode(int graphics) +-{ +- int fd, r; +- fd = open("/dev/tty0", O_RDWR | O_SYNC); +- if (fd < 0) +- return -1; +- r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT)); +- close(fd); +- return r; +-} +- +-/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */ +- +-int load_565rle_image(char *fn) +-{ +- struct FB fb; +- struct stat s; +- unsigned short *data, *bits, *ptr; +- unsigned count, max; +- int fd; +- +- if (vt_set_mode(1)) +- return -1; +- +- fd = open(fn, O_RDONLY); +- if (fd < 0) { +- ERROR("cannot open '%s'\n", fn); +- goto fail_restore_text; +- } +- +- if (fstat(fd, &s) < 0) { +- goto fail_close_file; +- } +- +- data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0); +- if (data == MAP_FAILED) +- goto fail_close_file; +- +- if (fb_open(&fb)) +- goto fail_unmap_data; +- +- max = fb_width(&fb) * fb_height(&fb); +- ptr = data; +- count = s.st_size; +- bits = fb.bits; +- while (count > 3) { +- unsigned n = ptr[0]; +- if (n > max) +- break; +- android_memset16(bits, ptr[1], n << 1); +- bits += n; +- max -= n; +- ptr += 2; +- count -= 4; +- } +- +- munmap(data, s.st_size); +- fb_update(&fb); +- fb_close(&fb); +- close(fd); +- unlink(fn); +- return 0; +- +-fail_unmap_data: +- munmap(data, s.st_size); +-fail_close_file: +- close(fd); +-fail_restore_text: +- vt_set_mode(0); +- return -1; +-} +- +-- +1.7.8.6 + |