summaryrefslogtreecommitdiff
path: root/system/core/0002-init-Support-DRM-KMS-to-display-the-boot-logo.patch
diff options
context:
space:
mode:
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.patch756
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
+