[PATCH 1/7] [ARM] s3c-fb: Added colorkey support
Pawel Osciak
p.osciak at samsung.com
Fri Sep 11 14:04:48 EDT 2009
Reviewed-by: Marek Szyprowski <m.szyprowski at samsung.com>
Reviewed-by: Kyungmin Park <kyungmin.park at samsung.com>
Signed-off-by: Pawel Osciak <p.osciak at samsung.com>
---
arch/arm/plat-s3c/include/plat/regs-fb.h | 3 +
arch/arm/plat-s3c/include/plat/s3c-fb.h | 45 ++++++++
drivers/video/s3c-fb.c | 164 ++++++++++++++++++++++++++++++
3 files changed, 212 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-s3c/include/plat/s3c-fb.h
diff --git a/arch/arm/plat-s3c/include/plat/regs-fb.h b/arch/arm/plat-s3c/include/plat/regs-fb.h
index 8048cae..8d3071d 100644
--- a/arch/arm/plat-s3c/include/plat/regs-fb.h
+++ b/arch/arm/plat-s3c/include/plat/regs-fb.h
@@ -323,6 +323,7 @@
/* Window colour-key control registers */
+#define WxKEYCON0(_x) (0x140 + ((_x-1) * 8))
#define WxKEYCON0_KEYBL_EN (1 << 26)
#define WxKEYCON0_KEYEN_F (1 << 25)
#define WxKEYCON0_DIRCON (1 << 24)
@@ -330,6 +331,8 @@
#define WxKEYCON0_COMPKEY_SHIFT (0)
#define WxKEYCON0_COMPKEY_LIMIT (0xffffff)
#define WxKEYCON0_COMPKEY(_x) ((_x) << 0)
+
+#define WxKEYCON1(_x) (0x144 + ((_x-1) * 8))
#define WxKEYCON1_COLVAL_MASK (0xffffff << 0)
#define WxKEYCON1_COLVAL_SHIFT (0)
#define WxKEYCON1_COLVAL_LIMIT (0xffffff)
diff --git a/arch/arm/plat-s3c/include/plat/s3c-fb.h b/arch/arm/plat-s3c/include/plat/s3c-fb.h
new file mode 100644
index 0000000..0aebc40
--- /dev/null
+++ b/arch/arm/plat-s3c/include/plat/s3c-fb.h
@@ -0,0 +1,45 @@
+/*
+ * include/linux/s3c/s3c-fb.h
+ *
+ * Copyright 2009 Samsung Electronics Co., Ltd.
+ * Author: Pawel Osciak <p.osciak at samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_S3C_FB_H__
+#define __LINUX_S3C_FB_H__
+
+#include <linux/types.h>
+
+struct s3c_fb_color {
+ __u32 a : 8;
+ __u32 r : 8;
+ __u32 g : 8;
+ __u32 b : 8;
+} __attribute__((__packed__));
+
+typedef enum s3c_fb_color_key_mode {
+ S3CFB_COLORKEY_MODE_BG = 0,
+ S3CFB_COLORKEY_MODE_FG = 1
+} s3c_fb_color_key_mode_t;
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, __u32)
+#endif
+
+#define S3CFB_IOCTL_MAGIC 'k'
+
+#define S3CFB_IOCTL_SET_COLOR_KEY _IOW(S3CFB_IOCTL_MAGIC, 0,\
+ struct s3c_fb_color)
+#define S3CFB_IOCTL_SET_COLOR_KEY_MASK _IOW(S3CFB_IOCTL_MAGIC, 1,\
+ struct s3c_fb_color)
+/* param: s3c_fb_color_key_mode */
+#define S3CFB_IOCTL_SET_COLOR_KEY_MODE _IO(S3CFB_IOCTL_MAGIC, 2)
+/* param: 1 - on, 0 - off */
+#define S3CFB_IOCTL_COLOR_KEY_ENABLE _IO(S3CFB_IOCTL_MAGIC, 3)
+
+#endif /* __LINUX_S3C_FB_H__ */
+
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c
index 001a1a1..2de3151 100644
--- a/drivers/video/s3c-fb.c
+++ b/drivers/video/s3c-fb.c
@@ -24,6 +24,8 @@
#include <linux/uaccess.h>
#include <linux/interrupt.h>
+#include <plat/s3c-fb.h>
+
#include <mach/map.h>
#include <mach/regs-fb.h>
#include <plat/fb.h>
@@ -43,6 +45,7 @@
* is being built for.
*/
+/*#define CONFIG_FB_S3C_DEBUG_REGWRITE*/
#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
#undef writel
#define writel(v, r) do { \
@@ -821,11 +824,148 @@ static int s3c_fb_pan_display(struct fb_var_screeninfo *var,
return 0;
}
+static inline int s3c_fb_color_to_rgb565(struct s3c_fb_color *color)
+{
+ return (((color->r & 0x1f) << 19) | 0x70000)
+ | (((color->g & 0x3f) << 10) | 0x300)
+ | (((color->b & 0x1f) << 3) | 0x7);
+}
+
+static inline int s3c_fb_color_to_rgb888(struct s3c_fb_color *color)
+{
+ return (color->r << 16) | (color->g << 8) | color->b;
+}
+
+static inline int has_colorkey(int win_no)
+{
+ if (win_no == 0)
+ return 0;
+ else
+ return 1;
+}
+
+static int s3c_fb_set_color_key(struct s3c_fb_win *win,
+ struct s3c_fb_color *color_key)
+{
+ struct s3c_fb *sfb = win->parent;
+ void __iomem *regs = sfb->regs;
+ int color = 0;
+
+ if (! has_colorkey(win->index)) {
+ dev_err(sfb->dev, "Window %d does not support color keying\n",
+ win->index);
+ return -EINVAL;
+ }
+
+ dev_info(sfb->dev, "Window %d, BPP: %d\n", win->index,
+ win->fbinfo->var.bits_per_pixel);
+
+ if (win->fbinfo->var.bits_per_pixel == 16) {
+ color = s3c_fb_color_to_rgb565(color_key);
+ } else if (win->fbinfo->var.bits_per_pixel >= 24) {
+ /*|| win->fbinfo->var.bits_per_pixel == 28) {*/
+ color = s3c_fb_color_to_rgb888(color_key);
+ } else {
+ dev_err(sfb->dev, "Invalid BPP\n");
+ return -EINVAL;
+ }
+
+ writel(color, regs + WxKEYCON1(win->index));
+
+ return 0;
+}
+
+static int s3c_fb_set_color_key_mask(struct s3c_fb_win *win,
+ struct s3c_fb_color *color_key_mask)
+{
+ struct s3c_fb *sfb = win->parent;
+ void __iomem *regs = sfb->regs;
+ int keycon0_reg;
+ int mask = 0;
+
+ if (! has_colorkey(win->index)) {
+ dev_err(sfb->dev, "Window %d does not support color keying\n",
+ win->index);
+ return -EINVAL;
+ }
+
+ if (win->fbinfo->var.bits_per_pixel == 16) {
+ mask = s3c_fb_color_to_rgb565(color_key_mask);
+ } else if (win->fbinfo->var.bits_per_pixel >= 24) {
+ /*|| win->fbinfo->var.bits_per_pixel == 28) {*/
+ mask = s3c_fb_color_to_rgb888(color_key_mask);
+ } else {
+ dev_err(sfb->dev, "Invalid BPP\n");
+ return -EINVAL;
+ }
+
+ keycon0_reg = readl(regs + WxKEYCON0(win->index));
+ keycon0_reg &= ~WxKEYCON0_COMPKEY_MASK;
+ keycon0_reg |= mask;
+ writel(keycon0_reg, regs + WxKEYCON0(win->index));
+
+ return 0;
+}
+
+static int s3c_fb_color_key_enable(struct s3c_fb_win *win, int enable)
+{
+ struct s3c_fb *sfb = win->parent;
+ int keycon0_reg;
+
+ if (! has_colorkey(win->index)) {
+ dev_err(sfb->dev, "Window does not support color keying\n");
+ return -EINVAL;
+ }
+
+ keycon0_reg = readl(sfb->regs + WxKEYCON0(win->index));
+ if (enable)
+ keycon0_reg |= WxKEYCON0_KEYEN_F;
+ else
+ keycon0_reg &= ~WxKEYCON0_KEYEN_F;
+
+ writel(keycon0_reg, sfb->regs + WxKEYCON0(win->index));
+
+ return 0;
+}
+
+static int s3c_fb_set_color_key_mode(struct s3c_fb_win *win,
+ enum s3c_fb_color_key_mode mode)
+{
+ struct s3c_fb *sfb = win->parent;
+ int keycon0_reg;
+
+ if (! has_colorkey(win->index)) {
+ dev_err(sfb->dev, "Window %d does not support color keying\n",
+ win->index);
+ return -EINVAL;
+ }
+
+ keycon0_reg = readl(sfb->regs + WxKEYCON0(win->index));
+
+ switch(mode) {
+ case S3CFB_COLORKEY_MODE_BG:
+ keycon0_reg &= ~WxKEYCON0_DIRCON;
+ break;
+ case S3CFB_COLORKEY_MODE_FG:
+ keycon0_reg |= WxKEYCON0_DIRCON;
+ break;
+ default:
+ dev_err(sfb->dev, "Invalid colorkey mode\n");
+ return -EINVAL;
+ }
+
+ writel(keycon0_reg, sfb->regs + WxKEYCON0(win->index));
+ s3c_fb_color_key_enable(win, 1);
+
+ return 0;
+}
+
static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
struct s3c_fb_win *win = info->par;
struct s3c_fb *sfb = win->parent;
+ int ret;
switch (cmd) {
case FBIO_WAITFORVSYNC: {
@@ -835,6 +975,30 @@ static int s3c_fb_ioctl(struct fb_info *info, unsigned int cmd,
return s3c_fb_wait_for_vsync(sfb, crtc);
}
+ case S3CFB_IOCTL_SET_COLOR_KEY: {
+ struct s3c_fb_color ck_arg;
+ ret = copy_from_user(&ck_arg, (void __user *)arg,
+ sizeof(struct s3c_fb_color));
+ if (ret)
+ return ret;
+
+ return s3c_fb_set_color_key(win, &ck_arg);
+ }
+ case S3CFB_IOCTL_SET_COLOR_KEY_MASK: {
+ struct s3c_fb_color ck_mask_arg;
+ ret = copy_from_user(&ck_mask_arg, (void __user *)arg,
+ sizeof(struct s3c_fb_color));
+ if (ret)
+ return ret;
+
+ return s3c_fb_set_color_key_mask(win, &ck_mask_arg);
+ }
+ case S3CFB_IOCTL_SET_COLOR_KEY_MODE:
+ return s3c_fb_set_color_key_mode(win, arg);
+
+ case S3CFB_IOCTL_COLOR_KEY_ENABLE:
+ return s3c_fb_color_key_enable(win, arg);
+
default:
return -ENOTTY;
}
--
1.6.4.2.253.g0b1fac
More information about the linux-arm-kernel
mailing list