From patchwork Tue Nov 3 13:54:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rongrong Zou X-Patchwork-Id: 7542531 Return-Path: X-Original-To: patchwork-linux-fbdev@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 48F8BBEEA4 for ; Tue, 3 Nov 2015 13:55:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 03273206B0 for ; Tue, 3 Nov 2015 13:55:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 85A6F20697 for ; Tue, 3 Nov 2015 13:55:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754183AbbKCNz2 (ORCPT ); Tue, 3 Nov 2015 08:55:28 -0500 Received: from blu004-omc3s20.hotmail.com ([65.55.116.95]:50873 "EHLO BLU004-OMC3S20.hotmail.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753915AbbKCNz2 (ORCPT ); Tue, 3 Nov 2015 08:55:28 -0500 Received: from BLU437-SMTP24 ([65.55.116.74]) by BLU004-OMC3S20.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Tue, 3 Nov 2015 05:55:27 -0800 X-TMN: [n7wiHovwxYJofRfzx1RfOHAJuwxF9jGn] X-Originating-Email: [rongrongchau@outlook.com] Message-ID: From: Rongrong Zou To: linux-fbdev@vger.kernel.org CC: linuxarm@huawei.com Subject: [PATCH 2/3] Hisilicon graphic driver: add hardware cursor support to hisilicon hi1710 graphi chip Date: Tue, 3 Nov 2015 21:54:57 +0800 X-Mailer: git-send-email 1.9.1 In-Reply-To: <1446558898-52857-1-git-send-email-rongrongchau@outlook.com> References: <1446558898-52857-1-git-send-email-rongrongchau@outlook.com> X-OriginalArrivalTime: 03 Nov 2015 13:55:26.0613 (UTC) FILETIME=[4AEB2450:01D1163F] MIME-Version: 1.0 Sender: linux-fbdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fbdev@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_HI,T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Rongrong Zou This patch implements hardware cursor. Signed-off-by: Rongrong Zou --- drivers/video/fbdev/hisilicon/Makefile | 2 +- drivers/video/fbdev/hisilicon/hisi_cursor.c | 121 ++++++++++++++++++++++++++++ drivers/video/fbdev/hisilicon/hisi_cursor.h | 11 +++ drivers/video/fbdev/hisilicon/hisi_drv.c | 88 ++++++++++++++++++++ 4 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 drivers/video/fbdev/hisilicon/hisi_cursor.c create mode 100644 drivers/video/fbdev/hisilicon/hisi_cursor.h diff --git a/drivers/video/fbdev/hisilicon/Makefile b/drivers/video/fbdev/hisilicon/Makefile index 540b6d2..5f478ed 100644 --- a/drivers/video/fbdev/hisilicon/Makefile +++ b/drivers/video/fbdev/hisilicon/Makefile @@ -1,6 +1,6 @@ obj-$(CONFIG_FB_HISILICON) += hisiliconfb.o -hisiliconfb-y := hisi_drv.o hisi_hw.o hisi_chip.o +hisiliconfb-y := hisi_drv.o hisi_hw.o hisi_cursor.o hisi_chip.o hisiliconfb-y += hisi_mode.o hisi_power.o hisiliconfb-objs := $(hisiliconfb-y) diff --git a/drivers/video/fbdev/hisilicon/hisi_cursor.c b/drivers/video/fbdev/hisilicon/hisi_cursor.c new file mode 100644 index 0000000..84b0156 --- /dev/null +++ b/drivers/video/fbdev/hisilicon/hisi_cursor.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hisi_drv.h" +#include "hisi_cursor.h" +#include "hisi_help.h" +#include "hisi_reg.h" + + +#define WRITE_REG(addr, data) writel((data), cursor->mmio + (addr)) + + +void hw_cursor_enable(struct hisi_cursor *cursor) +{ + u32 reg; + + reg = FIELD_VALUE(0, HWC_ADDRESS, ADDRESS, cursor->offset) | + FIELD_SET(0, HWC_ADDRESS, EXT, LOCAL) | + FIELD_SET(0, HWC_ADDRESS, ENABLE, ENABLE); + WRITE_REG(HWC_ADDRESS, reg); +} + +void hw_cursor_disable(struct hisi_cursor *cursor) +{ + WRITE_REG(HWC_ADDRESS, 0); +} + +void hw_cursor_set_size(struct hisi_cursor *cursor, int w, int h) +{ + cursor->w = w; + cursor->h = h; +} + +void hw_cursor_set_pos(struct hisi_cursor *cursor, int x, int y) +{ + u32 reg; + + reg = FIELD_VALUE(0, HWC_LOCATION, Y, y) | + FIELD_VALUE(0, HWC_LOCATION, X, x); + WRITE_REG(HWC_LOCATION, reg); +} + +void hw_cursor_set_color(struct hisi_cursor *cursor, u32 fg, u32 bg) +{ + WRITE_REG(HWC_COLOR_12, (fg << 16)|(bg & 0xffff)); + WRITE_REG(HWC_COLOR_3, 0xffe0); +} + +void hw_cursor_set_data(struct hisi_cursor *cursor, + u16 rop, const u8 *pcol, const u8 *pmsk) +{ + struct hisifb_crtc *crtc; + + int i, j, count, pitch, offset; + u8 color, mask, opr; + u16 data; + u16 *pbuffer, *pstart; + + crtc = container_of(cursor, struct hisifb_crtc, cursor); + /* in byte*/ + pitch = cursor->w >> 3; + + /* in byte */ + count = pitch * cursor->h; + + /* in ushort */ + offset = cursor->maxW * 2 / 8 / 2; + + data = 0; + pstart = (u16 *)cursor->vstart; + pbuffer = pstart; + + + for (i = 0; i < count; i++) { + color = *pcol++; + mask = *pmsk++; + data = 0; + + /* either method below works well, + * but method 2 shows no lag + * and method 1 seems a bit wrong + */ + + for (j = 0; j < 8; j++) { + if (mask & (0x80 >> j)) { + if (rop == ROP_XOR) + opr = mask ^ color; + else + opr = mask & color; + + /* 2 stands for forecolor and 1 for backcolor */ + data |= ((opr & (0x80 >> j)) ? 2 : 1) << + (j * 2); + } + } + + *pbuffer = data; + + /* assume pitch is 1,2,4,8,...*/ + if ((i+1) % pitch == 0) { + /* need a return */ + pstart += offset; + pbuffer = pstart; + } else { + pbuffer++; + } + } +} diff --git a/drivers/video/fbdev/hisilicon/hisi_cursor.h b/drivers/video/fbdev/hisilicon/hisi_cursor.h new file mode 100644 index 0000000..551b743 --- /dev/null +++ b/drivers/video/fbdev/hisilicon/hisi_cursor.h @@ -0,0 +1,11 @@ +#ifndef HISI_CURSOR_H__ +#define HISI_CURSOR_H__ + +void hw_cursor_enable(struct hisi_cursor *cursor); +void hw_cursor_disable(struct hisi_cursor *cursor); +void hw_cursor_set_size(struct hisi_cursor *cursor, int w, int h); +void hw_cursor_set_pos(struct hisi_cursor *cursor, int x, int y); +void hw_cursor_set_color(struct hisi_cursor *cursor, u32 fg, u32 bg); +void hw_cursor_set_data(struct hisi_cursor *cursor, u16 rop, + const u8 *data, const u8 *mask); +#endif diff --git a/drivers/video/fbdev/hisilicon/hisi_drv.c b/drivers/video/fbdev/hisilicon/hisi_drv.c index 521a279..54231d3 100644 --- a/drivers/video/fbdev/hisilicon/hisi_drv.c +++ b/drivers/video/fbdev/hisilicon/hisi_drv.c @@ -18,6 +18,7 @@ #include #include #include "hisi_drv.h" +#include "hisi_cursor.h" #include "hisi_hw.h" @@ -37,6 +38,7 @@ static int hisifb_ops_set_par(struct fb_info *); static int hisifb_ops_setcolreg(unsigned, unsigned, unsigned, unsigned, unsigned, struct fb_info *); static int hisifb_ops_blank(int, struct fb_info *); +static int hisifb_ops_cursor(struct fb_info *, struct fb_cursor *); typedef void (*PROC_SPEC_SETUP)(struct hisi_share *, char *); typedef int (*PROC_SPEC_MAP)(struct hisi_share *, struct pci_dev *); @@ -128,6 +130,63 @@ static struct pci_driver hisifb_driver = { #endif }; +static int hisifb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor) +{ + struct hisifb_par *par; + struct hisifb_crtc *crtc; + struct hisi_cursor *cursor; + + par = info->par; + crtc = &par->crtc; + cursor = &crtc->cursor; + + if (fbcursor->image.width > cursor->maxW || + fbcursor->image.height > cursor->maxH || + fbcursor->image.depth > 1){ + return -ENXIO; + } + + cursor->disable(cursor); + if (fbcursor->set & FB_CUR_SETSIZE) + cursor->set_size(cursor, fbcursor->image.width, + fbcursor->image.height); + + + if (fbcursor->set & FB_CUR_SETPOS) + cursor->set_pos(cursor, fbcursor->image.dx - info->var.xoffset, + fbcursor->image.dy - info->var.yoffset); + + if (fbcursor->set & FB_CUR_SETCMAP) { + /* get the 16bit color of kernel means */ + u16 fg, bg; + + fg = + ((info->cmap.red[fbcursor->image.fg_color] & 0xf800)) | + ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5)| + ((info->cmap.blue[fbcursor->image.fg_color] & 0xf800) >> 11); + + bg = + ((info->cmap.red[fbcursor->image.bg_color] & 0xf800))| + ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5)| + ((info->cmap.blue[fbcursor->image.bg_color] & 0xf800) >> 11); + + cursor->set_color(cursor, fg, bg); + } + + + if (fbcursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { + cursor->set_data(cursor, + fbcursor->rop, + fbcursor->image.data, + fbcursor->mask); + } + + if (fbcursor->enable) + cursor->enable(cursor); + + return 0; +} + static struct fb_ops hisifb_ops = { .owner = THIS_MODULE, .fb_check_var = hisifb_ops_check_var, @@ -138,6 +197,8 @@ static struct fb_ops hisifb_ops = { .fb_fillrect = cfb_fillrect, .fb_imageblit = cfb_imageblit, .fb_copyarea = cfb_copyarea, + /* cursor */ + .fb_cursor = hisifb_ops_cursor, }; #ifdef CONFIG_PM @@ -621,6 +682,33 @@ static int hisifb_set_fbinfo(struct fb_info *info, int index) output->channel = &crtc->channel; hisifb_set_drv(par); + /* + * Set current cursor variable and proc pointer, + * must be set after crtc member initialized. + */ + crtc->cursor.offset = crtc->oscreen + + crtc->vidmem_size - 1024; + crtc->cursor.mmio = share->pvreg + 0x800f0 + + (int)crtc->channel * 0x140; + + inf_msg("crtc->cursor.mmio = %p\n", crtc->cursor.mmio); + crtc->cursor.maxH = crtc->cursor.maxW = 64; + crtc->cursor.size = crtc->cursor.maxH * + crtc->cursor.maxW * 2 / 8; + crtc->cursor.disable = hw_cursor_disable; + crtc->cursor.enable = hw_cursor_enable; + crtc->cursor.set_color = hw_cursor_set_color; + crtc->cursor.set_pos = hw_cursor_set_pos; + crtc->cursor.set_size = hw_cursor_set_size; + crtc->cursor.set_data = hw_cursor_set_data; + crtc->cursor.vstart = crtc->vscreen + crtc->cursor.offset; + + crtc->cursor.share = share; + if (!g_hwcursor) { + hisifb_ops.fb_cursor = NULL; + crtc->cursor.disable(&crtc->cursor); + } + /* set info->fbops, must be set before fb_find_mode */ info->fbops = &hisifb_ops;