// SPDX-License-Identifier: GPL-2.0-only
/*
* linux/drivers/video/w100fb.c
*
* Frame Buffer Device for ATI Imageon w100 (Wallaby)
*
* Copyright (C) 2002, ATI Corp.
* Copyright (C) 2004-2006 Richard Purdie
* Copyright (c) 2005 Ian Molton
* Copyright (c) 2006 Alberto Mardegan
*
* Rewritten for 2.6 by Richard Purdie <rpurdie@rpsys.net>
*
* Generic platform support by Ian Molton <spyro@f2s.com>
* and Richard Purdie <rpurdie@rpsys.net>
*
* w32xx support by Ian Molton
*
* Hardware acceleration support by Alberto Mardegan
* <mardy@users.sourceforge.net>
*/
#include <linux/delay.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/vmalloc.h>
#include <linux/module.h>
#include <asm/io.h>
#include <linux/uaccess.h>
#include <video/w100fb.h>
#include "w100fb.h"
/*
* Prototypes
*/
static void w100_suspend(u32 mode);
static void w100_vsync(void);
static void w100_hw_init(struct w100fb_par*);
static void w100_pwm_setup(struct w100fb_par*);
static void w100_init_clocks(struct w100fb_par*);
static void w100_setup_memory(struct w100fb_par*);
static void w100_init_lcd(struct w100fb_par*);
static void w100_set_dispregs(struct w100fb_par*);
static void w100_update_enable(void);
static void w100_update_disable(void);
static void calc_hsync(struct w100fb_par *par);
static void w100_init_graphic_engine(struct w100fb_par *par);
struct w100_pll_info *w100_get_xtal_table(unsigned int freq);
/* Pseudo palette size */
#define MAX_PALETTES 16
#define W100_SUSPEND_EXTMEM 0
#define W100_SUSPEND_ALL 1
#define BITS_PER_PIXEL 16
/* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
static void *remapped_base;
static void *remapped_regs;
static void *remapped_fbuf;
#define REMAPPED_FB_LEN 0x15ffff
/* This is the offset in the w100's address space we map the current
framebuffer memory to. We use the position of external memory as
we can remap internal memory to there if external isn't present. */
#define W100_FB_BASE MEM_EXT_BASE_VALUE
/*
* Sysfs functions
*/
static ssize_t flip_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
return sprintf(buf, "%d\n",par->flip);
}
static ssize_t flip_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned int flip;
struct fb_info *info = dev_get_drvdata(dev);
struct w100fb_par *par=info->par;
flip = simple_strtoul(buf, NULL, 10);
if (flip > 0)
par->flip = 1;
else
par->flip = 0;
w100_update_disable();
w100_set_dispregs(par);
w100_update_enable();
calc_hsync(par);
return count;
}
static DEVICE_ATTR_RW(flip);
static ssize_t w100fb_reg_read(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long regs, param;
regs = simple_strtoul(buf, NULL, 16);
param = readl(remapped_regs + regs);
printk("Read Register 0x%08lX: 0x%08lX\n", regs, param);
return count;
}
static DEVICE_ATTR(reg_read, 0200, NULL, w100fb_reg_read);
static ssize_t w100fb_reg_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
unsigned long regs, param;
sscanf(buf, "%lx %lx", ®s, ¶m);
if (regs <= 0x2000) {
printk("Write Register 0x%08lX: 0x%08lX\n", regs, param);
writel(param, remapped_r
|