/*
* Common code for AUO-K190X framebuffer drivers
*
* Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
*
* 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.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/pm_runtime.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h>
#include <linux/regulator/consumer.h>
#include <video/auo_k190xfb.h>
#include "auo_k190x.h"
struct panel_info {
int w;
int h;
};
/* table of panel specific parameters to be indexed into by the board drivers */
static struct panel_info panel_table[] = {
/* standard 6" */
[AUOK190X_RESOLUTION_800_600] = {
.w = 800,
.h = 600,
},
/* standard 9" */
[AUOK190X_RESOLUTION_1024_768] = {
.w = 1024,
.h = 768,
},
};
/*
* private I80 interface to the board driver
*/
static void auok190x_issue_data(struct auok190xfb_par *par, u16 data)
{
par->board->set_ctl(par, AUOK190X_I80_WR, 0);
par->board->set_hdb(par, data);
par->board->set_ctl(par, AUOK190X_I80_WR, 1);
}
static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
{
par->board->set_ctl(par, AUOK190X_I80_DC, 0);
auok190x_issue_data(par, data);
par->board->set_ctl(par, AUOK190X_I80_DC, 1);
}
static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
u16 *data)
{
struct device *dev = par->info->device;
int i;
u16 tmp;
if (size & 3) {
dev_err(dev, "issue_pixels: size %d must be a multiple of 4\n",
size);
return -EINVAL;
}
for (i = 0; i < (size >> 1); i++) {
par->board->set_ctl(par, AUOK190X_I80_WR, 0);
/* simple reduction of 8bit staticgray to 4bit gray
* combines 4 * 4bit pixel values into a 16bit value
*/
tmp = (data[2*i] & 0xF0) >> 4;
tmp |= (data[2*i] & 0xF000) >> 8;
tmp |= (data[2*i+1] & 0xF0) << 4;
tmp |= (data[2*i+1] & 0xF000);
par->board->set_hdb(par, tmp);
par->board->set_ctl(par, AUOK190X_I80_WR, 1);
}
return 0;
}
static u16 auok190x_read_data(struct auok190xfb_par *par)
{
u16 data;
par->board->set_ctl(par, AUOK190X_I80_OE, 0);
data = par->board->get_hdb(par);
par->board->set_ctl(par, AUOK190X_I80_OE, 1);
return data;
}
/*
* Command interface for the controller drivers
*/
void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data)
{
par->board->set_ctl(par, AUOK190X_I80_CS, 0);
auok190x_issue_cmd(par, data);
par->board->set_ctl(par, AUOK190X_I80_CS, 1);
}
EXPORT_SYMBOL_GPL(auok190x_send_command_nowait);
void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
int argc, u16 *argv)
{
int i;
par->board->set_ctl(par, AUOK190X_I80_CS, 0);
auok190x_issue_cmd(par, cmd);
for (i = 0; i < argc; i++)
auok190x_issue_data(par, argv[i]);
par->board->set_ctl(par, AUOK190X_I80_CS, 1);
}
EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_nowait);
int auok190x_send_command(struct auok190xfb_par *par, u16 data)
{
int ret;
ret = par->board->wait_for_rdy(par);