/*
* Copyright 2012 Red Hat Inc.
* Parts based on xf86-video-ast
* Copyright (c) 2005 ASPEED Technology Inc.
*
* 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*/
/*
* Authors: Dave Airlie <airlied@redhat.com>
*/
#include <linux/delay.h>
#include <linux/pci.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_color_mgmt.h>
#include <drm/drm_crtc.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_panic.h>
#include <drm/drm_print.h>
#include <drm/drm_probe_helper.h>
#include "ast_drv.h"
#include "ast_tables.h"
#include "ast_vbios.h"
#define AST_LUT_SIZE 256
#define AST_PRIMARY_PLANE_MAX_OFFSET (BIT(16) - 1)
static unsigned long ast_fb_vram_offset(void)
{
return 0; // with shmem, the primary plane is always at offset 0
}
static unsigned long ast_fb_vram_size(struct ast_device *ast)
{
struct drm_device *dev = &ast->base;
unsigned long offset = ast_fb_vram_offset(); // starts at offset
long cursor_offset = ast_cursor_vram_offset(ast); // ends at cursor offset
if (cursor_offset < 0)
cursor_offset = ast->vram_size; // no cursor; it's all ours
if (drm_WARN_ON_ONCE(dev, offset > cursor_offset))
return 0; // cannot legally happen; signal error
return cursor_offset - offset;
}
static void ast_set_gamma_lut(struct drm_crtc *crtc, unsigned int index,
u16 red, u16 green, u16 blue)
{
struct drm_device *dev = crtc->dev;
struct ast_device *ast = to_ast_device(dev);
u8 i8 = index & 0xff;
u8 r8 = red >> 8;
u8 g8 = green >> 8;
u8 b8 = blue >> 8;
if (drm_WARN_ON_ONCE(dev, index != i8))
return; /* driver bug */
ast_io_write8(ast, AST_IO_VGADWR, i8);
ast_io_read8(ast, AST_IO_VGASRI);
ast_io_write8(ast, AST_IO_VGAPDR, r8);
ast_io_read8(ast, AST_IO_VGASRI);
ast_io_write8(ast, AST_IO_VGAPDR, g8);
ast_io_read8(ast, AST_IO_VGASRI);
ast_io_write8(ast, AST_IO_VGAPDR, b8);
ast_io_read8(ast, AST_IO_VGASRI);
}
static void ast_crtc_fill_gamma(struct ast_device *ast,
const struct drm_format_info *format)
{
struct drm_crtc *crtc = &ast->crtc;
switch (format->format) {
case DRM_FORMAT_C8:
/* gamma table is used as color palette */
drm_crtc_fill_palette_8(crtc, ast_set_gamma_lut);
break;
case DRM_FORMAT_RGB565:
/* also uses 8-bit gamma ramp on low-color modes */
fallthrough;
case DRM_FORMAT_XRGB8888:
drm_crtc_fill_gamma_888(crtc, ast_set_gamma_lut);
break;
default:
drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
&format->format);
break;
}
}
static void ast_crtc_load_gamma(struct ast_device *ast,
const struct drm_format_info *format,
struct drm_color_lut *lut)
{
struct drm_crtc *crtc = &ast->crtc;
switch (format->format) {
case DRM_FORMAT_C8:
/* gamma table is used as color palette */
drm_crtc_load_palette_8(crtc, lut, ast_set_gamma_lut);
break;
case DRM_FORMAT_RGB565:
/* also uses 8-bit gamma ramp on low-color modes */
fallthrough;
case DRM_FORMAT_XRGB8888:
drm_crtc_load_gamma_888(crtc, lut, ast_set_gamma_lut);
break;
default:
drm_warn_once(&ast->base,<