Commit bf7c7a6c authored by Siarhei Siamashka's avatar Siarhei Siamashka
Browse files

Added supplementary wrapper functions for sunxi display controller ioctls

Note: the header file "sunxi_disp_ioctl.h" is GPL licensed. So until
it is gets a MIT/X11 replacement, the DDX driver is GPL licensed as
a whole. The individual source files still have their own license.
Also in order to avoid any possible confusion, the MIT/X11 license
header from COPYING has been added to "fbdev.c" and "fbdev_priv.h".
parent b0813ddf
......@@ -21,3 +21,22 @@ Except as contained in this notice, the name of the XFree86 Project shall not
be used in advertising or otherwise to promote the sale, use or other deal-
ings in this Software without prior written authorization from the XFree86
Project.
/*
* Copyright (C) 2007-2012 Allwinner Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
......@@ -31,4 +31,6 @@ sunxifb_drv_ladir = @moduledir@/drivers
sunxifb_drv_la_SOURCES = \
compat-api.h \
fbdev.c \
fbdev_priv.h
fbdev_priv.h \
sunxi_disp.c \
sunxi_disp.h
/*
* Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is fur-
* nished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
* NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
* NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the XFree86 Project shall not
* be used in advertising or otherwise to promote the sale, use or other deal-
* ings in this Software without prior written authorization from the XFree86
* Project.
*/
/*
* Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
* Michel Dänzer, <michel@tungstengraphics.com>
......@@ -20,6 +46,8 @@
#include "shadow.h"
#include "dgaproc.h"
#include "sunxi_disp.h"
/* for visuals */
#include "fb.h"
......@@ -888,6 +916,9 @@ FBDevScreenInit(SCREEN_INIT_ARGS_DECL)
}
#endif
fPtr->sunxi_disp_private = sunxi_disp_init(xf86FindOptionValue(
fPtr->pEnt->device->options,"fbdev"));
TRACE_EXIT("FBDevScreenInit");
return TRUE;
......@@ -898,7 +929,13 @@ FBDevCloseScreen(CLOSE_SCREEN_ARGS_DECL)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
FBDevPtr fPtr = FBDEVPTR(pScrn);
if (fPtr->sunxi_disp_private) {
sunxi_disp_close(fPtr->sunxi_disp_private);
free(fPtr->sunxi_disp_private);
fPtr->sunxi_disp_private = NULL;
}
fbdevHWRestore(pScrn);
fbdevHWUnmapVidmem(pScrn);
if (fPtr->shadow) {
......
/*
* Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is fur-
* nished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
* NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
* NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the XFree86 Project shall not
* be used in advertising or otherwise to promote the sale, use or other deal-
* ings in this Software without prior written authorization from the XFree86
* Project.
*/
/*
* Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk>
* Michel Dänzer, <michel@tungstengraphics.com>
......@@ -21,6 +47,11 @@ typedef struct {
DGAModePtr pDGAMode;
int nDGAMode;
OptionInfoPtr Options;
void *sunxi_disp_private;;
} FBDevRec, *FBDevPtr;
#define FBDEVPTR(p) ((FBDevPtr)((p)->driverPrivate))
#define SUNXI_DISP(p) ((sunxi_disp_t *) \
(FBDEVPTR(p)->sunxi_disp_private))
/*
* Copyright © 2013 Siarhei Siamashka <siarhei.siamashka@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <inttypes.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "sunxi_disp.h"
#include "sunxi_disp_ioctl.h"
/*****************************************************************************/
sunxi_disp_t *sunxi_disp_init(const char *device)
{
sunxi_disp_t *ctx = calloc(sizeof(sunxi_disp_t), 1);
struct fb_var_screeninfo fb_var;
struct fb_fix_screeninfo fb_fix;
int tmp, version;
int gfx_layer_size;
int ovl_layer_size;
if (strcmp(device, "/dev/fb0") == 0) {
ctx->fb_id = 0;
}
else if (strcmp(device, "/dev/fb1") == 0) {
ctx->fb_id = 1;
}
else
{
free(ctx);
return NULL;
}
ctx->fd_disp = open("/dev/disp", O_RDWR);
/* maybe it's even not a sunxi hardware */
if (ctx->fd_disp < 0) {
free(ctx);
return NULL;
}
/* version check */
tmp = SUNXI_DISP_VERSION;
version = ioctl(ctx->fd_disp, DISP_CMD_VERSION, &tmp);
if (version < 0) {
close(ctx->fd_disp);
free(ctx);
return NULL;
}
ctx->fd_fb = open(device, O_RDWR);
if (ctx->fd_fb < 0) {
close(ctx->fd_disp);
free(ctx);
return NULL;
}
if (ioctl(ctx->fd_fb, FBIOGET_VSCREENINFO, &fb_var) < 0 ||
ioctl(ctx->fd_fb, FBIOGET_FSCREENINFO, &fb_fix) < 0)
{
close(ctx->fd_fb);
close(ctx->fd_disp);
free(ctx);
return NULL;
}
ctx->xres = fb_var.xres;
ctx->yres = fb_var.yres;
ctx->bits_per_pixel = fb_var.bits_per_pixel;
ctx->framebuffer_paddr = fb_fix.smem_start;
ctx->framebuffer_size = fb_fix.smem_len;
ctx->gfx_layer_size = ctx->xres * ctx->yres * fb_var.bits_per_pixel / 8;
if (ctx->framebuffer_size < ctx->gfx_layer_size) {
close(ctx->fd_fb);
close(ctx->fd_disp);
free(ctx);
return NULL;
}
/* mmap framebuffer memory */
ctx->framebuffer_addr = (uint8_t *)mmap(0, ctx->framebuffer_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, ctx->fd_fb, 0);
if (ctx->framebuffer_addr == MAP_FAILED) {
close(ctx->fd_fb);
close(ctx->fd_disp);
free(ctx);
return NULL;
}
ctx->cursor_enabled = 0;
ctx->cursor_x = -1;
ctx->cursor_y = -1;
if (sunxi_layer_reserve(ctx) < 0)
{
close(ctx->fd_fb);
close(ctx->fd_disp);
free(ctx);
return NULL;
}
return ctx;
}
int sunxi_disp_close(sunxi_disp_t *ctx)
{
if (ctx->fd_disp >= 0) {
/* release layer */
sunxi_layer_release(ctx);
/* disable cursor */
if (ctx->cursor_enabled)
sunxi_hw_cursor_hide(ctx);
/* close descriptors */
munmap(ctx->framebuffer_addr, ctx->framebuffer_size);
close(ctx->fd_fb);
close(ctx->fd_disp);
ctx->fd_disp = -1;
}
return 0;
}
/*****************************************************************************
* Support for hardware cursor, which has 64x64 size, 2 bits per pixel, *
* four 32-bit ARGB entries in the palette. *
*****************************************************************************/
int sunxi_hw_cursor_load_pixeldata(sunxi_disp_t *ctx, uint8_t pixeldata[1024])
{
uint32_t tmp[4];
__disp_hwc_pattern_t hwc;
hwc.addr = (uintptr_t)&pixeldata[0];
hwc.pat_mode = DISP_HWC_MOD_H64_V64_2BPP;
tmp[0] = ctx->fb_id;
tmp[1] = (uintptr_t)&hwc;
return ioctl(ctx->fd_disp, DISP_CMD_HWC_SET_FB, &tmp);
}
int sunxi_hw_cursor_load_palette(sunxi_disp_t *ctx, uint32_t palette[4])
{
uint32_t tmp[4];
tmp[0] = ctx->fb_id;
tmp[1] = (uintptr_t)&palette[0];
tmp[2] = 0;
tmp[3] = 4 * sizeof(uint32_t);
return ioctl(ctx->fd_disp, DISP_CMD_HWC_SET_PALETTE_TABLE, &tmp);
}
int sunxi_hw_cursor_set_position(sunxi_disp_t *ctx, int x, int y)
{
int result;
uint32_t tmp[4];
__disp_pos_t pos = { x, y };
tmp[0] = ctx->fb_id;
tmp[1] = (uintptr_t)&pos;
if (pos.x < 0)
pos.x = 0;
if (pos.y < 0)
pos.y = 0;
result = ioctl(ctx->fd_disp, DISP_CMD_HWC_SET_POS, &tmp);
if (result >= 0) {
ctx->cursor_x = pos.x;
ctx->cursor_y = pos.y;
}
return result;
}
int sunxi_hw_cursor_show(sunxi_disp_t *ctx)
{
int result;
uint32_t tmp[4];
tmp[0] = ctx->fb_id;
result = ioctl(ctx->fd_disp, DISP_CMD_HWC_OPEN, &tmp);
if (result >= 0)
ctx->cursor_enabled = 1;
return result;
}
int sunxi_hw_cursor_hide(sunxi_disp_t *ctx)
{
int result;
uint32_t tmp[4];
tmp[0] = ctx->fb_id;
result = ioctl(ctx->fd_disp, DISP_CMD_HWC_CLOSE, &tmp);
if (result >= 0)
ctx->cursor_enabled = 0;
return result;
}
/*****************************************************************************
* Support for scaled layers *
*****************************************************************************/
int sunxi_layer_reserve(sunxi_disp_t *ctx)
{
__disp_layer_info_t layer_info;
uint32_t tmp[4];
/* try to allocate a layer */
tmp[0] = ctx->fb_id;
tmp[1] = DISP_LAYER_WORK_MODE_NORMAL;
ctx->layer_id = ioctl(ctx->fd_disp, DISP_CMD_LAYER_REQUEST, &tmp);
if (ctx->layer_id < 0)
return -1;
/* also try to enable scaler for this layer */
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&layer_info;
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_GET_PARA, tmp) < 0)
return ctx->layer_id;
layer_info.mode = DISP_LAYER_WORK_MODE_SCALER;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&layer_info;
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_PARA, tmp) >= 0)
ctx->layer_has_scaler = 1;
return ctx->layer_id;
}
int sunxi_layer_release(sunxi_disp_t *ctx)
{
int result;
uint32_t tmp[4];
if (ctx->layer_id < 0)
return -1;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
ioctl(ctx->fd_disp, DISP_CMD_LAYER_RELEASE, &tmp);
ctx->layer_id = -1;
ctx->layer_has_scaler = 0;
return 0;
}
int sunxi_layer_set_x8r8g8b8_input_buffer(sunxi_disp_t *ctx,
uint32_t offset_in_framebuffer,
int width,
int height,
int stride)
{
__disp_fb_t fb;
__disp_rect_t rect = { 0, 0, width, height };
uint32_t tmp[4];
memset(&fb, 0, sizeof(fb));
if (ctx->layer_id < 0)
return -1;
fb.addr[0] = ctx->framebuffer_paddr + offset_in_framebuffer;
fb.size.width = stride;
fb.size.height = height;
fb.format = DISP_FORMAT_ARGB8888;
fb.seq = DISP_SEQ_ARGB;
fb.mode = DISP_MOD_INTERLEAVED;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&fb;
if (ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_FB, &tmp) < 0)
return -1;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&rect;
return ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_SRC_WINDOW, &tmp);
}
int sunxi_layer_set_output_window(sunxi_disp_t *ctx, int x, int y, int w, int h)
{
__disp_rect_t rect = { x, y, w, h };
uint32_t tmp[4];
if (ctx->layer_id < 0)
return -1;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
tmp[2] = (uintptr_t)&rect;
return ioctl(ctx->fd_disp, DISP_CMD_LAYER_SET_SCN_WINDOW, &tmp);
}
int sunxi_layer_show(sunxi_disp_t *ctx)
{
uint32_t tmp[4];
if (ctx->layer_id < 0)
return -1;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
return ioctl(ctx->fd_disp, DISP_CMD_LAYER_OPEN, &tmp);
}
int sunxi_layer_hide(sunxi_disp_t *ctx)
{
int result;
uint32_t tmp[4];
if (ctx->layer_id < 0)
return -1;
tmp[0] = ctx->fb_id;
tmp[1] = ctx->layer_id;
return ioctl(ctx->fd_disp, DISP_CMD_LAYER_CLOSE, &tmp);
}
/*****************************************************************************/
int sunxi_wait_for_vsync(sunxi_disp_t *ctx)
{
return ioctl(ctx->fd_fb, FBIO_WAITFORVSYNC, 0);
}
/*
* Copyright © 2013 Siarhei Siamashka <siarhei.siamashka@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef SUNXI_DISP_H
#define SUNXI_DISP_H
#include <inttypes.h>
/*
* Support for Allwinner A10 display controller features such as layers
* and hardware cursor
*/
typedef struct {
int fd_fb;
int fd_disp;
int fb_id; /* /dev/fb0 = 0, /dev/fb1 = 1 */
int xres, yres, bits_per_pixel;
uint8_t *framebuffer_addr; /* mmapped address */
uintptr_t framebuffer_paddr; /* physical address */
uint32_t framebuffer_size; /* total size of the framebuffer */
uint32_t gfx_layer_size; /* the size of the primary layer */
/* Hardware cursor support */
int cursor_enabled;
int cursor_x, cursor_y;
/* Layers support */
int layer_id;
int layer_has_scaler;
} sunxi_disp_t;
sunxi_disp_t *sunxi_disp_init(const char *fb_device);
int sunxi_disp_close(sunxi_disp_t *ctx);
/*
* Support for hardware cursor, which has 64x64 size, 2 bits per pixel,
* four 32-bit ARGB entries in the palette.
*/
int sunxi_hw_cursor_load_pixeldata(sunxi_disp_t *ctx, uint8_t pixeldata[1024]);
int sunxi_hw_cursor_load_palette(sunxi_disp_t *ctx, uint32_t palette[4]);
int sunxi_hw_cursor_set_position(sunxi_disp_t *ctx, int x, int y);
int sunxi_hw_cursor_show(sunxi_disp_t *ctx);
int sunxi_hw_cursor_hide(sunxi_disp_t *ctx);
/*
* Support for one sunxi disp layer (even though there are more than
* one available) in the offscreen part of framebuffer, which may be
* useful for DRI2 vsync aware frame flipping and implementing XV
* extension (video overlay).
*/
int sunxi_layer_reserve(sunxi_disp_t *ctx);
int sunxi_layer_release(sunxi_disp_t *ctx);
int sunxi_layer_set_x8r8g8b8_input_buffer(sunxi_disp_t *ctx,
uint32_t offset_in_framebuffer,
int width,
int height,
int stride);
int sunxi_layer_set_output_window(sunxi_disp_t *ctx, int x, int y, int w, int h);
int sunxi_layer_show(sunxi_disp_t *ctx);
int sunxi_layer_hide(sunxi_disp_t *ctx);
/*
* Wait for vsync
*/
int sunxi_wait_for_vsync(sunxi_disp_t *ctx);
#endif
This diff is collapsed.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment