auo_k1900fb and auo_k1901fb drivers have been introduced six years ago by following commits: commit 2c8304d3125b ("video: auo_k190x: add code shared by controller drivers") commit 96b1d500e028 ("video: auo_k190x: add driver for AUO-K1900 variant") commit 53027cdf2a67 ("video: auo_k190x: add driver for AUO-K1901 variant") They never had any in-kernel user so just remove them (since they are platform drivers they need corresponding platform devices to be registered by kernel and it has never happened). Cc: Heiko Stübner <heiko@xxxxxxxxx> Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@xxxxxxxxxxx> --- drivers/video/fbdev/Kconfig | 33 - drivers/video/fbdev/Makefile | 3 drivers/video/fbdev/auo_k1900fb.c | 204 ------ drivers/video/fbdev/auo_k1901fb.c | 257 -------- drivers/video/fbdev/auo_k190x.c | 1190 -------------------------------------- drivers/video/fbdev/auo_k190x.h | 129 ---- include/video/auo_k190xfb.h | 107 --- 7 files changed, 1923 deletions(-) Index: b/drivers/video/fbdev/Kconfig =================================================================== --- a/drivers/video/fbdev/Kconfig 2018-04-26 14:54:03.656207576 +0200 +++ b/drivers/video/fbdev/Kconfig 2018-04-26 15:23:47.772252506 +0200 @@ -2253,39 +2253,6 @@ config FB_BROADSHEET and could also have been called by other names when coupled with a bridge adapter. -config FB_AUO_K190X - tristate "AUO-K190X EPD controller support" - depends on FB - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - help - Provides support for epaper controllers from the K190X series - of AUO. These controllers can be used to drive epaper displays - from Sipix. - - This option enables the common support, shared by the individual - controller drivers. You will also have to enable the driver - for the controller type used in your device. - -config FB_AUO_K1900 - tristate "AUO-K1900 EPD controller support" - depends on FB && FB_AUO_K190X - help - This driver implements support for the AUO K1900 epd-controller. - This controller can drive Sipix epaper displays but can only do - serial updates, reducing the number of possible frames per second. - -config FB_AUO_K1901 - tristate "AUO-K1901 EPD controller support" - depends on FB && FB_AUO_K190X - help - This driver implements support for the AUO K1901 epd-controller. - This controller can drive Sipix epaper displays and supports - concurrent updates, making higher frames per second possible. - config FB_JZ4740 tristate "JZ4740 LCD framebuffer support" depends on FB && MACH_JZ4740 Index: b/drivers/video/fbdev/Makefile =================================================================== --- a/drivers/video/fbdev/Makefile 2018-04-24 16:53:10.043083317 +0200 +++ b/drivers/video/fbdev/Makefile 2018-04-26 15:25:42.128255386 +0200 @@ -100,9 +100,6 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb obj-$(CONFIG_FB_MAXINE) += maxinefb.o obj-$(CONFIG_FB_METRONOME) += metronomefb.o obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o -obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o -obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o -obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o obj-$(CONFIG_FB_SH7760) += sh7760fb.o obj-$(CONFIG_FB_IMX) += imxfb.o Index: b/drivers/video/fbdev/auo_k1900fb.c =================================================================== --- a/drivers/video/fbdev/auo_k1900fb.c 2017-10-18 14:35:21.947448311 +0200 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,204 +0,0 @@ -/* - * auok190xfb.c -- FB driver for AUO-K1900 controllers - * - * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@xxxxxxxxx> - * - * based on broadsheetfb.c - * - * Copyright (C) 2008, Jaya Kumar - * - * 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. - * - * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. - * - * This driver is written to be used with the AUO-K1900 display controller. - * - * It is intended to be architecture independent. A board specific driver - * must be used to perform all the physical IO interactions. - * - * The controller supports different update modes: - * mode0+1 16 step gray (4bit) - * mode2 4 step gray (2bit) - FIXME: add strange refresh - * mode3 2 step gray (1bit) - FIXME: add strange refresh - * mode4 handwriting mode (strange behaviour) - * mode5 automatic selection of update mode - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/list.h> -#include <linux/firmware.h> -#include <linux/gpio.h> -#include <linux/pm_runtime.h> - -#include <video/auo_k190xfb.h> - -#include "auo_k190x.h" - -/* - * AUO-K1900 specific commands - */ - -#define AUOK1900_CMD_PARTIALDISP 0x1001 -#define AUOK1900_CMD_ROTATION 0x1006 -#define AUOK1900_CMD_LUT_STOP 0x1009 - -#define AUOK1900_INIT_TEMP_AVERAGE (1 << 13) -#define AUOK1900_INIT_ROTATE(_x) ((_x & 0x3) << 10) -#define AUOK1900_INIT_RESOLUTION(_res) ((_res & 0x7) << 2) - -static void auok1900_init(struct auok190xfb_par *par) -{ - struct device *dev = par->info->device; - struct auok190x_board *board = par->board; - u16 init_param = 0; - - pm_runtime_get_sync(dev); - - init_param |= AUOK1900_INIT_TEMP_AVERAGE; - init_param |= AUOK1900_INIT_ROTATE(par->rotation); - init_param |= AUOK190X_INIT_INVERSE_WHITE; - init_param |= AUOK190X_INIT_FORMAT0; - init_param |= AUOK1900_INIT_RESOLUTION(par->resolution); - init_param |= AUOK190X_INIT_SHIFT_RIGHT; - - auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param); - - /* let the controller finish */ - board->wait_for_rdy(par); - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); -} - -static void auok1900_update_region(struct auok190xfb_par *par, int mode, - u16 y1, u16 y2) -{ - struct device *dev = par->info->device; - unsigned char *buf = (unsigned char *)par->info->screen_base; - int xres = par->info->var.xres; - int line_length = par->info->fix.line_length; - u16 args[4]; - - pm_runtime_get_sync(dev); - - mutex_lock(&(par->io_lock)); - - /* y1 and y2 must be a multiple of 2 so drop the lowest bit */ - y1 &= 0xfffe; - y2 &= 0xfffe; - - dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n", - 1, y1+1, xres, y2-y1, mode); - - /* to FIX handle different partial update modes */ - args[0] = mode | 1; - args[1] = y1 + 1; - args[2] = xres; - args[3] = y2 - y1; - buf += y1 * line_length; - auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args, - ((y2 - y1) * line_length)/2, (u16 *) buf); - auok190x_send_command(par, AUOK190X_CMD_DATA_STOP); - - par->update_cnt++; - - mutex_unlock(&(par->io_lock)); - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); -} - -static void auok1900fb_dpy_update_pages(struct auok190xfb_par *par, - u16 y1, u16 y2) -{ - int mode; - - if (par->update_mode < 0) { - mode = AUOK190X_UPDATE_MODE(1); - par->last_mode = -1; - } else { - mode = AUOK190X_UPDATE_MODE(par->update_mode); - par->last_mode = par->update_mode; - } - - if (par->flash) - mode |= AUOK190X_UPDATE_NONFLASH; - - auok1900_update_region(par, mode, y1, y2); -} - -static void auok1900fb_dpy_update(struct auok190xfb_par *par) -{ - int mode; - - if (par->update_mode < 0) { - mode = AUOK190X_UPDATE_MODE(0); - par->last_mode = -1; - } else { - mode = AUOK190X_UPDATE_MODE(par->update_mode); - par->last_mode = par->update_mode; - } - - if (par->flash) - mode |= AUOK190X_UPDATE_NONFLASH; - - auok1900_update_region(par, mode, 0, par->info->var.yres); - par->update_cnt = 0; -} - -static bool auok1900fb_need_refresh(struct auok190xfb_par *par) -{ - return (par->update_cnt > 10); -} - -static int auok1900fb_probe(struct platform_device *pdev) -{ - struct auok190x_init_data init; - struct auok190x_board *board; - - /* pick up board specific routines */ - board = pdev->dev.platform_data; - if (!board) - return -EINVAL; - - /* fill temporary init struct for common init */ - init.id = "auo_k1900fb"; - init.board = board; - init.update_partial = auok1900fb_dpy_update_pages; - init.update_all = auok1900fb_dpy_update; - init.need_refresh = auok1900fb_need_refresh; - init.init = auok1900_init; - - return auok190x_common_probe(pdev, &init); -} - -static int auok1900fb_remove(struct platform_device *pdev) -{ - return auok190x_common_remove(pdev); -} - -static struct platform_driver auok1900fb_driver = { - .probe = auok1900fb_probe, - .remove = auok1900fb_remove, - .driver = { - .name = "auo_k1900fb", - .pm = &auok190x_pm, - }, -}; -module_platform_driver(auok1900fb_driver); - -MODULE_DESCRIPTION("framebuffer driver for the AUO-K1900 EPD controller"); -MODULE_AUTHOR("Heiko Stuebner <heiko@xxxxxxxxx>"); -MODULE_LICENSE("GPL"); Index: b/drivers/video/fbdev/auo_k1901fb.c =================================================================== --- a/drivers/video/fbdev/auo_k1901fb.c 2017-10-18 14:35:21.947448311 +0200 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,257 +0,0 @@ -/* - * auok190xfb.c -- FB driver for AUO-K1901 controllers - * - * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@xxxxxxxxx> - * - * based on broadsheetfb.c - * - * Copyright (C) 2008, Jaya Kumar - * - * 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. - * - * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven. - * - * This driver is written to be used with the AUO-K1901 display controller. - * - * It is intended to be architecture independent. A board specific driver - * must be used to perform all the physical IO interactions. - * - * The controller supports different update modes: - * mode0+1 16 step gray (4bit) - * mode2+3 4 step gray (2bit) - * mode4+5 2 step gray (1bit) - * - mode4 is described as "without LUT" - * mode7 automatic selection of update mode - * - * The most interesting difference to the K1900 is the ability to do screen - * updates in an asynchronous fashion. Where the K1900 needs to wait for the - * current update to complete, the K1901 can process later updates already. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/list.h> -#include <linux/firmware.h> -#include <linux/gpio.h> -#include <linux/pm_runtime.h> - -#include <video/auo_k190xfb.h> - -#include "auo_k190x.h" - -/* - * AUO-K1901 specific commands - */ - -#define AUOK1901_CMD_LUT_INTERFACE 0x0005 -#define AUOK1901_CMD_DMA_START 0x1001 -#define AUOK1901_CMD_CURSOR_START 0x1007 -#define AUOK1901_CMD_CURSOR_STOP AUOK190X_CMD_DATA_STOP -#define AUOK1901_CMD_DDMA_START 0x1009 - -#define AUOK1901_INIT_GATE_PULSE_LOW (0 << 14) -#define AUOK1901_INIT_GATE_PULSE_HIGH (1 << 14) -#define AUOK1901_INIT_SINGLE_GATE (0 << 13) -#define AUOK1901_INIT_DOUBLE_GATE (1 << 13) - -/* Bits to pixels - * Mode 15-12 11-8 7-4 3-0 - * format2 2 T 1 T - * format3 1 T 2 T - * format4 T 2 T 1 - * format5 T 1 T 2 - * - * halftone modes: - * format6 2 2 1 1 - * format7 1 1 2 2 - */ -#define AUOK1901_INIT_FORMAT2 (1 << 7) -#define AUOK1901_INIT_FORMAT3 ((1 << 7) | (1 << 6)) -#define AUOK1901_INIT_FORMAT4 (1 << 8) -#define AUOK1901_INIT_FORMAT5 ((1 << 8) | (1 << 6)) -#define AUOK1901_INIT_FORMAT6 ((1 << 8) | (1 << 7)) -#define AUOK1901_INIT_FORMAT7 ((1 << 8) | (1 << 7) | (1 << 6)) - -/* res[4] to bit 10 - * res[3-0] to bits 5-2 - */ -#define AUOK1901_INIT_RESOLUTION(_res) (((_res & (1 << 4)) << 6) \ - | ((_res & 0xf) << 2)) - -/* - * portrait / landscape orientation in AUOK1901_CMD_DMA_START - */ -#define AUOK1901_DMA_ROTATE90(_rot) ((_rot & 1) << 13) - -/* - * equivalent to 1 << 11, needs the ~ to have same rotation like K1900 - */ -#define AUOK1901_DDMA_ROTATE180(_rot) ((~_rot & 2) << 10) - -static void auok1901_init(struct auok190xfb_par *par) -{ - struct device *dev = par->info->device; - struct auok190x_board *board = par->board; - u16 init_param = 0; - - pm_runtime_get_sync(dev); - - init_param |= AUOK190X_INIT_INVERSE_WHITE; - init_param |= AUOK190X_INIT_FORMAT0; - init_param |= AUOK1901_INIT_RESOLUTION(par->resolution); - init_param |= AUOK190X_INIT_SHIFT_LEFT; - - auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param); - - /* let the controller finish */ - board->wait_for_rdy(par); - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); -} - -static void auok1901_update_region(struct auok190xfb_par *par, int mode, - u16 y1, u16 y2) -{ - struct device *dev = par->info->device; - unsigned char *buf = (unsigned char *)par->info->screen_base; - int xres = par->info->var.xres; - int line_length = par->info->fix.line_length; - u16 args[5]; - - pm_runtime_get_sync(dev); - - mutex_lock(&(par->io_lock)); - - /* y1 and y2 must be a multiple of 2 so drop the lowest bit */ - y1 &= 0xfffe; - y2 &= 0xfffe; - - dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n", - 1, y1+1, xres, y2-y1, mode); - - /* K1901: first transfer the region data */ - args[0] = AUOK1901_DMA_ROTATE90(par->rotation) | 1; - args[1] = y1 + 1; - args[2] = xres; - args[3] = y2 - y1; - buf += y1 * line_length; - auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4, - args, ((y2 - y1) * line_length)/2, - (u16 *) buf); - auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP); - - /* K1901: second tell the controller to update the region with mode */ - args[0] = mode | AUOK1901_DDMA_ROTATE180(par->rotation); - args[1] = 1; - args[2] = y1 + 1; - args[3] = xres; - args[4] = y2 - y1; - auok190x_send_cmdargs_nowait(par, AUOK1901_CMD_DDMA_START, 5, args); - - par->update_cnt++; - - mutex_unlock(&(par->io_lock)); - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); -} - -static void auok1901fb_dpy_update_pages(struct auok190xfb_par *par, - u16 y1, u16 y2) -{ - int mode; - - if (par->update_mode < 0) { - mode = AUOK190X_UPDATE_MODE(1); - par->last_mode = -1; - } else { - mode = AUOK190X_UPDATE_MODE(par->update_mode); - par->last_mode = par->update_mode; - } - - if (par->flash) - mode |= AUOK190X_UPDATE_NONFLASH; - - auok1901_update_region(par, mode, y1, y2); -} - -static void auok1901fb_dpy_update(struct auok190xfb_par *par) -{ - int mode; - - /* When doing full updates, wait for the controller to be ready - * This will hopefully catch some hangs of the K1901 - */ - par->board->wait_for_rdy(par); - - if (par->update_mode < 0) { - mode = AUOK190X_UPDATE_MODE(0); - par->last_mode = -1; - } else { - mode = AUOK190X_UPDATE_MODE(par->update_mode); - par->last_mode = par->update_mode; - } - - if (par->flash) - mode |= AUOK190X_UPDATE_NONFLASH; - - auok1901_update_region(par, mode, 0, par->info->var.yres); - par->update_cnt = 0; -} - -static bool auok1901fb_need_refresh(struct auok190xfb_par *par) -{ - return (par->update_cnt > 10); -} - -static int auok1901fb_probe(struct platform_device *pdev) -{ - struct auok190x_init_data init; - struct auok190x_board *board; - - /* pick up board specific routines */ - board = pdev->dev.platform_data; - if (!board) - return -EINVAL; - - /* fill temporary init struct for common init */ - init.id = "auo_k1901fb"; - init.board = board; - init.update_partial = auok1901fb_dpy_update_pages; - init.update_all = auok1901fb_dpy_update; - init.need_refresh = auok1901fb_need_refresh; - init.init = auok1901_init; - - return auok190x_common_probe(pdev, &init); -} - -static int auok1901fb_remove(struct platform_device *pdev) -{ - return auok190x_common_remove(pdev); -} - -static struct platform_driver auok1901fb_driver = { - .probe = auok1901fb_probe, - .remove = auok1901fb_remove, - .driver = { - .name = "auo_k1901fb", - .pm = &auok190x_pm, - }, -}; -module_platform_driver(auok1901fb_driver); - -MODULE_DESCRIPTION("framebuffer driver for the AUO-K1901 EPD controller"); -MODULE_AUTHOR("Heiko Stuebner <heiko@xxxxxxxxx>"); -MODULE_LICENSE("GPL"); Index: b/drivers/video/fbdev/auo_k190x.c =================================================================== --- a/drivers/video/fbdev/auo_k190x.c 2018-04-26 14:54:03.672207576 +0200 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,1190 +0,0 @@ -/* - * Common code for AUO-K190X framebuffer drivers - * - * Copyright (C) 2012 Heiko Stuebner <heiko@xxxxxxxxx> - * - * 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/sched/mm.h> -#include <linux/kernel.h> -#include <linux/gpio.h> -#include <linux/platform_device.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, - }, - [AUOK190X_RESOLUTION_600_800] = { - .w = 600, - .h = 800, - }, - [AUOK190X_RESOLUTION_768_1024] = { - .w = 768, - .h = 1024, - }, -}; - -/* - * 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); -} - -/** - * Conversion of 16bit color to 4bit grayscale - * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2 - */ -static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var) -{ - return ((((data & 0xF800) >> var->red.offset) * 77 + - ((data & 0x07E0) >> (var->green.offset + 1)) * 151 + - ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1); -} - -static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size, - u16 *data) -{ - struct fb_var_screeninfo *var = &par->info->var; - struct device *dev = par->info->device; - int i; - u16 tmp; - - if (size & 7) { - dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n", - size); - return -EINVAL; - } - - for (i = 0; i < (size >> 2); i++) { - par->board->set_ctl(par, AUOK190X_I80_WR, 0); - - tmp = (rgb565_to_gray4(data[4*i], var) & 0x000F); - tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0; - tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00; - tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000; - - par->board->set_hdb(par, tmp); - par->board->set_ctl(par, AUOK190X_I80_WR, 1); - } - - return 0; -} - -static int auok190x_issue_pixels_gray8(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 int auok190x_issue_pixels(struct auok190xfb_par *par, int size, - u16 *data) -{ - struct fb_info *info = par->info; - struct device *dev = par->info->device; - - if (info->var.bits_per_pixel == 8 && info->var.grayscale) - auok190x_issue_pixels_gray8(par, size, data); - else if (info->var.bits_per_pixel == 16) - auok190x_issue_pixels_rgb565(par, size, data); - else - dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n", - info->var.bits_per_pixel, info->var.grayscale); - - 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); - if (ret) - return ret; - - auok190x_send_command_nowait(par, data); - return 0; -} -EXPORT_SYMBOL_GPL(auok190x_send_command); - -int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd, - int argc, u16 *argv) -{ - int ret; - - ret = par->board->wait_for_rdy(par); - if (ret) - return ret; - - auok190x_send_cmdargs_nowait(par, cmd, argc, argv); - return 0; -} -EXPORT_SYMBOL_GPL(auok190x_send_cmdargs); - -int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd, - int argc, u16 *argv) -{ - int i, ret; - - ret = par->board->wait_for_rdy(par); - if (ret) - return ret; - - par->board->set_ctl(par, AUOK190X_I80_CS, 0); - auok190x_issue_cmd(par, cmd); - - for (i = 0; i < argc; i++) - argv[i] = auok190x_read_data(par); - par->board->set_ctl(par, AUOK190X_I80_CS, 1); - - return 0; -} -EXPORT_SYMBOL_GPL(auok190x_read_cmdargs); - -void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par, u16 cmd, - int argc, u16 *argv, int size, u16 *data) -{ - 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]); - - auok190x_issue_pixels(par, size, data); - - par->board->set_ctl(par, AUOK190X_I80_CS, 1); -} -EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels_nowait); - -int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd, - int argc, u16 *argv, int size, u16 *data) -{ - int ret; - - ret = par->board->wait_for_rdy(par); - if (ret) - return ret; - - auok190x_send_cmdargs_pixels_nowait(par, cmd, argc, argv, size, data); - - return 0; -} -EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels); - -/* - * fbdefio callbacks - common on both controllers. - */ - -static void auok190xfb_dpy_first_io(struct fb_info *info) -{ - /* tell runtime-pm that we wish to use the device in a short time */ - pm_runtime_get(info->device); -} - -/* this is called back from the deferred io workqueue */ -static void auok190xfb_dpy_deferred_io(struct fb_info *info, - struct list_head *pagelist) -{ - struct fb_deferred_io *fbdefio = info->fbdefio; - struct auok190xfb_par *par = info->par; - u16 line_length = info->fix.line_length; - u16 yres = info->var.yres; - u16 y1 = 0, h = 0; - int prev_index = -1; - struct page *cur; - int h_inc; - int threshold; - - if (!list_empty(pagelist)) - /* the device resume should've been requested through first_io, - * if the resume did not finish until now, wait for it. - */ - pm_runtime_barrier(info->device); - else - /* We reached this via the fsync or some other way. - * In either case the first_io function did not run, - * so we runtime_resume the device here synchronously. - */ - pm_runtime_get_sync(info->device); - - /* Do a full screen update every n updates to prevent - * excessive darkening of the Sipix display. - * If we do this, there is no need to walk the pages. - */ - if (par->need_refresh(par)) { - par->update_all(par); - goto out; - } - - /* height increment is fixed per page */ - h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length); - - /* calculate number of pages from pixel height */ - threshold = par->consecutive_threshold / h_inc; - if (threshold < 1) - threshold = 1; - - /* walk the written page list and swizzle the data */ - list_for_each_entry(cur, &fbdefio->pagelist, lru) { - if (prev_index < 0) { - /* just starting so assign first page */ - y1 = (cur->index << PAGE_SHIFT) / line_length; - h = h_inc; - } else if ((cur->index - prev_index) <= threshold) { - /* page is within our threshold for single updates */ - h += h_inc * (cur->index - prev_index); - } else { - /* page not consecutive, issue previous update first */ - par->update_partial(par, y1, y1 + h); - - /* start over with our non consecutive page */ - y1 = (cur->index << PAGE_SHIFT) / line_length; - h = h_inc; - } - prev_index = cur->index; - } - - /* if we still have any pages to update we do so now */ - if (h >= yres) - /* its a full screen update, just do it */ - par->update_all(par); - else - par->update_partial(par, y1, min((u16) (y1 + h), yres)); - -out: - pm_runtime_mark_last_busy(info->device); - pm_runtime_put_autosuspend(info->device); -} - -/* - * framebuffer operations - */ - -/* - * this is the slow path from userspace. they can seek and write to - * the fb. it's inefficient to do anything less than a full screen draw - */ -static ssize_t auok190xfb_write(struct fb_info *info, const char __user *buf, - size_t count, loff_t *ppos) -{ - struct auok190xfb_par *par = info->par; - unsigned long p = *ppos; - void *dst; - int err = 0; - unsigned long total_size; - - if (info->state != FBINFO_STATE_RUNNING) - return -EPERM; - - total_size = info->fix.smem_len; - - if (p > total_size) - return -EFBIG; - - if (count > total_size) { - err = -EFBIG; - count = total_size; - } - - if (count + p > total_size) { - if (!err) - err = -ENOSPC; - - count = total_size - p; - } - - dst = (void *)(info->screen_base + p); - - if (copy_from_user(dst, buf, count)) - err = -EFAULT; - - if (!err) - *ppos += count; - - par->update_all(par); - - return (err) ? err : count; -} - -static void auok190xfb_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct auok190xfb_par *par = info->par; - - sys_fillrect(info, rect); - - par->update_all(par); -} - -static void auok190xfb_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - struct auok190xfb_par *par = info->par; - - sys_copyarea(info, area); - - par->update_all(par); -} - -static void auok190xfb_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct auok190xfb_par *par = info->par; - - sys_imageblit(info, image); - - par->update_all(par); -} - -static int auok190xfb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info) -{ - struct device *dev = info->device; - struct auok190xfb_par *par = info->par; - struct panel_info *panel = &panel_table[par->resolution]; - int size; - - /* - * Color depth - */ - - if (var->bits_per_pixel == 8 && var->grayscale == 1) { - /* - * For 8-bit grayscale, R, G, and B offset are equal. - */ - var->red.length = 8; - var->red.offset = 0; - var->red.msb_right = 0; - - var->green.length = 8; - var->green.offset = 0; - var->green.msb_right = 0; - - var->blue.length = 8; - var->blue.offset = 0; - var->blue.msb_right = 0; - - var->transp.length = 0; - var->transp.offset = 0; - var->transp.msb_right = 0; - } else if (var->bits_per_pixel == 16) { - var->red.length = 5; - var->red.offset = 11; - var->red.msb_right = 0; - - var->green.length = 6; - var->green.offset = 5; - var->green.msb_right = 0; - - var->blue.length = 5; - var->blue.offset = 0; - var->blue.msb_right = 0; - - var->transp.length = 0; - var->transp.offset = 0; - var->transp.msb_right = 0; - } else { - dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n", - info->var.bits_per_pixel, info->var.grayscale); - return -EINVAL; - } - - /* - * Dimensions - */ - - switch (var->rotate) { - case FB_ROTATE_UR: - case FB_ROTATE_UD: - var->xres = panel->w; - var->yres = panel->h; - break; - case FB_ROTATE_CW: - case FB_ROTATE_CCW: - var->xres = panel->h; - var->yres = panel->w; - break; - default: - dev_dbg(dev, "Invalid rotation request\n"); - return -EINVAL; - } - - var->xres_virtual = var->xres; - var->yres_virtual = var->yres; - - /* - * Memory limit - */ - - size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8; - if (size > info->fix.smem_len) { - dev_err(dev, "Memory limit exceeded, requested %dK\n", - size >> 10); - return -ENOMEM; - } - - return 0; -} - -static int auok190xfb_set_fix(struct fb_info *info) -{ - struct fb_fix_screeninfo *fix = &info->fix; - struct fb_var_screeninfo *var = &info->var; - - fix->line_length = var->xres_virtual * var->bits_per_pixel / 8; - - fix->type = FB_TYPE_PACKED_PIXELS; - fix->accel = FB_ACCEL_NONE; - fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR - : FB_VISUAL_TRUECOLOR; - fix->xpanstep = 0; - fix->ypanstep = 0; - fix->ywrapstep = 0; - - return 0; -} - -static int auok190xfb_set_par(struct fb_info *info) -{ - struct auok190xfb_par *par = info->par; - - par->rotation = info->var.rotate; - auok190xfb_set_fix(info); - - /* reinit the controller to honor the rotation */ - par->init(par); - - /* wait for init to complete */ - par->board->wait_for_rdy(par); - - return 0; -} - -static struct fb_ops auok190xfb_ops = { - .owner = THIS_MODULE, - .fb_read = fb_sys_read, - .fb_write = auok190xfb_write, - .fb_fillrect = auok190xfb_fillrect, - .fb_copyarea = auok190xfb_copyarea, - .fb_imageblit = auok190xfb_imageblit, - .fb_check_var = auok190xfb_check_var, - .fb_set_par = auok190xfb_set_par, -}; - -/* - * Controller-functions common to both K1900 and K1901 - */ - -static int auok190x_read_temperature(struct auok190xfb_par *par) -{ - struct device *dev = par->info->device; - u16 data[4]; - int temp; - - pm_runtime_get_sync(dev); - - mutex_lock(&(par->io_lock)); - - auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data); - - mutex_unlock(&(par->io_lock)); - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - - /* sanitize and split of half-degrees for now */ - temp = ((data[0] & AUOK190X_VERSION_TEMP_MASK) >> 1); - - /* handle positive and negative temperatures */ - if (temp >= 201) - return (255 - temp + 1) * (-1); - else - return temp; -} - -static void auok190x_identify(struct auok190xfb_par *par) -{ - struct device *dev = par->info->device; - u16 data[4]; - - pm_runtime_get_sync(dev); - - mutex_lock(&(par->io_lock)); - - auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data); - - mutex_unlock(&(par->io_lock)); - - par->epd_type = data[1] & AUOK190X_VERSION_TEMP_MASK; - - par->panel_size_int = AUOK190X_VERSION_SIZE_INT(data[2]); - par->panel_size_float = AUOK190X_VERSION_SIZE_FLOAT(data[2]); - par->panel_model = AUOK190X_VERSION_MODEL(data[2]); - - par->tcon_version = AUOK190X_VERSION_TCON(data[3]); - par->lut_version = AUOK190X_VERSION_LUT(data[3]); - - dev_dbg(dev, "panel %d.%din, model 0x%x, EPD 0x%x TCON-rev 0x%x, LUT-rev 0x%x", - par->panel_size_int, par->panel_size_float, par->panel_model, - par->epd_type, par->tcon_version, par->lut_version); - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); -} - -/* - * Sysfs functions - */ - -static ssize_t update_mode_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - - return sprintf(buf, "%d\n", par->update_mode); -} - -static ssize_t update_mode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - int mode, ret; - - ret = kstrtoint(buf, 10, &mode); - if (ret) - return ret; - - par->update_mode = mode; - - /* if we enter a better mode, do a full update */ - if (par->last_mode > 1 && mode < par->last_mode) - par->update_all(par); - - return count; -} - -static ssize_t flash_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - - return sprintf(buf, "%d\n", par->flash); -} - -static ssize_t flash_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - int flash, ret; - - ret = kstrtoint(buf, 10, &flash); - if (ret) - return ret; - - if (flash > 0) - par->flash = 1; - else - par->flash = 0; - - return count; -} - -static ssize_t temp_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - int temp; - - temp = auok190x_read_temperature(par); - return sprintf(buf, "%d\n", temp); -} - -static DEVICE_ATTR_RW(update_mode); -static DEVICE_ATTR_RW(flash); -static DEVICE_ATTR(temp, 0644, temp_show, NULL); - -static struct attribute *auok190x_attributes[] = { - &dev_attr_update_mode.attr, - &dev_attr_flash.attr, - &dev_attr_temp.attr, - NULL -}; - -static const struct attribute_group auok190x_attr_group = { - .attrs = auok190x_attributes, -}; - -static int auok190x_power(struct auok190xfb_par *par, bool on) -{ - struct auok190x_board *board = par->board; - int ret; - - if (on) { - /* We should maintain POWER up for at least 80ms before set - * RST_N and SLP_N to high (TCON spec 20100803_v35 p59) - */ - ret = regulator_enable(par->regulator); - if (ret) - return ret; - - msleep(200); - gpio_set_value(board->gpio_nrst, 1); - gpio_set_value(board->gpio_nsleep, 1); - msleep(200); - } else { - regulator_disable(par->regulator); - gpio_set_value(board->gpio_nrst, 0); - gpio_set_value(board->gpio_nsleep, 0); - } - - return 0; -} - -/* - * Recovery - powercycle the controller - */ - -static void auok190x_recover(struct auok190xfb_par *par) -{ - struct device *dev = par->info->device; - - auok190x_power(par, 0); - msleep(100); - auok190x_power(par, 1); - - /* after powercycling the device, it's always active */ - pm_runtime_set_active(dev); - par->standby = 0; - - par->init(par); - - /* wait for init to complete */ - par->board->wait_for_rdy(par); -} - -/* - * Power-management - */ -static int __maybe_unused auok190x_runtime_suspend(struct device *dev) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - struct auok190x_board *board = par->board; - u16 standby_param; - - /* take and keep the lock until we are resumed, as the controller - * will never reach the non-busy state when in standby mode - */ - mutex_lock(&(par->io_lock)); - - if (par->standby) { - dev_warn(dev, "already in standby, runtime-pm pairing mismatch\n"); - mutex_unlock(&(par->io_lock)); - return 0; - } - - /* according to runtime_pm.txt runtime_suspend only means, that the - * device will not process data and will not communicate with the CPU - * As we hold the lock, this stays true even without standby - */ - if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) { - dev_dbg(dev, "runtime suspend without standby\n"); - goto finish; - } else if (board->quirks & AUOK190X_QUIRK_STANDBYPARAM) { - /* for some TCON versions STANDBY expects a parameter (0) but - * it seems the real tcon version has to be determined yet. - */ - dev_dbg(dev, "runtime suspend with additional empty param\n"); - standby_param = 0; - auok190x_send_cmdargs(par, AUOK190X_CMD_STANDBY, 1, - &standby_param); - } else { - dev_dbg(dev, "runtime suspend without param\n"); - auok190x_send_command(par, AUOK190X_CMD_STANDBY); - } - - msleep(64); - -finish: - par->standby = 1; - - return 0; -} - -static int __maybe_unused auok190x_runtime_resume(struct device *dev) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - struct auok190x_board *board = par->board; - - if (!par->standby) { - dev_warn(dev, "not in standby, runtime-pm pairing mismatch\n"); - return 0; - } - - if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) { - dev_dbg(dev, "runtime resume without standby\n"); - } else { - /* when in standby, controller is always busy - * and only accepts the wakeup command - */ - dev_dbg(dev, "runtime resume from standby\n"); - auok190x_send_command_nowait(par, AUOK190X_CMD_WAKEUP); - - msleep(160); - - /* wait for the controller to be ready and release the lock */ - board->wait_for_rdy(par); - } - - par->standby = 0; - - mutex_unlock(&(par->io_lock)); - - return 0; -} - -static int __maybe_unused auok190x_suspend(struct device *dev) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - struct auok190x_board *board = par->board; - int ret; - - dev_dbg(dev, "suspend\n"); - if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) { - /* suspend via powering off the ic */ - dev_dbg(dev, "suspend with broken standby\n"); - - auok190x_power(par, 0); - } else { - dev_dbg(dev, "suspend using sleep\n"); - - /* the sleep state can only be entered from the standby state. - * pm_runtime_get_noresume gets called before the suspend call. - * So the devices usage count is >0 but it is not necessarily - * active. - */ - if (!pm_runtime_status_suspended(dev)) { - ret = auok190x_runtime_suspend(dev); - if (ret < 0) { - dev_err(dev, "auok190x_runtime_suspend failed with %d\n", - ret); - return ret; - } - par->manual_standby = 1; - } - - gpio_direction_output(board->gpio_nsleep, 0); - } - - msleep(100); - - return 0; -} - -static int __maybe_unused auok190x_resume(struct device *dev) -{ - struct fb_info *info = dev_get_drvdata(dev); - struct auok190xfb_par *par = info->par; - struct auok190x_board *board = par->board; - - dev_dbg(dev, "resume\n"); - if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) { - dev_dbg(dev, "resume with broken standby\n"); - - auok190x_power(par, 1); - - par->init(par); - } else { - dev_dbg(dev, "resume from sleep\n"); - - /* device should be in runtime suspend when we were suspended - * and pm_runtime_put_sync gets called after this function. - * So there is no need to touch the standby mode here at all. - */ - gpio_direction_output(board->gpio_nsleep, 1); - msleep(100); - - /* an additional init call seems to be necessary after sleep */ - auok190x_runtime_resume(dev); - par->init(par); - - /* if we were runtime-suspended before, suspend again*/ - if (!par->manual_standby) - auok190x_runtime_suspend(dev); - else - par->manual_standby = 0; - } - - return 0; -} - -const struct dev_pm_ops auok190x_pm = { - SET_RUNTIME_PM_OPS(auok190x_runtime_suspend, auok190x_runtime_resume, - NULL) - SET_SYSTEM_SLEEP_PM_OPS(auok190x_suspend, auok190x_resume) -}; -EXPORT_SYMBOL_GPL(auok190x_pm); - -/* - * Common probe and remove code - */ - -int auok190x_common_probe(struct platform_device *pdev, - struct auok190x_init_data *init) -{ - struct auok190x_board *board = init->board; - struct auok190xfb_par *par; - struct fb_info *info; - struct panel_info *panel; - int videomemorysize, ret; - unsigned char *videomemory; - - /* check board contents */ - if (!board->init || !board->cleanup || !board->wait_for_rdy - || !board->set_ctl || !board->set_hdb || !board->get_hdb - || !board->setup_irq) - return -EINVAL; - - info = framebuffer_alloc(sizeof(struct auok190xfb_par), &pdev->dev); - if (!info) - return -ENOMEM; - - par = info->par; - par->info = info; - par->board = board; - par->recover = auok190x_recover; - par->update_partial = init->update_partial; - par->update_all = init->update_all; - par->need_refresh = init->need_refresh; - par->init = init->init; - - /* init update modes */ - par->update_cnt = 0; - par->update_mode = -1; - par->last_mode = -1; - par->flash = 0; - - par->regulator = regulator_get(info->device, "vdd"); - if (IS_ERR(par->regulator)) { - ret = PTR_ERR(par->regulator); - dev_err(info->device, "Failed to get regulator: %d\n", ret); - goto err_reg; - } - - ret = board->init(par); - if (ret) { - dev_err(info->device, "board init failed, %d\n", ret); - goto err_board; - } - - ret = gpio_request(board->gpio_nsleep, "AUOK190x sleep"); - if (ret) { - dev_err(info->device, "could not request sleep gpio, %d\n", - ret); - goto err_gpio1; - } - - ret = gpio_direction_output(board->gpio_nsleep, 0); - if (ret) { - dev_err(info->device, "could not set sleep gpio, %d\n", ret); - goto err_gpio2; - } - - ret = gpio_request(board->gpio_nrst, "AUOK190x reset"); - if (ret) { - dev_err(info->device, "could not request reset gpio, %d\n", - ret); - goto err_gpio2; - } - - ret = gpio_direction_output(board->gpio_nrst, 0); - if (ret) { - dev_err(info->device, "could not set reset gpio, %d\n", ret); - goto err_gpio3; - } - - ret = auok190x_power(par, 1); - if (ret) { - dev_err(info->device, "could not power on the device, %d\n", - ret); - goto err_gpio3; - } - - mutex_init(&par->io_lock); - - init_waitqueue_head(&par->waitq); - - ret = par->board->setup_irq(par->info); - if (ret) { - dev_err(info->device, "could not setup ready-irq, %d\n", ret); - goto err_irq; - } - - /* wait for init to complete */ - par->board->wait_for_rdy(par); - - /* - * From here on the controller can talk to us - */ - - /* initialise fix, var, resolution and rotation */ - - strlcpy(info->fix.id, init->id, 16); - info->var.bits_per_pixel = 8; - info->var.grayscale = 1; - - panel = &panel_table[board->resolution]; - - par->resolution = board->resolution; - par->rotation = 0; - - /* videomemory handling */ - - videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE); - videomemory = vzalloc(videomemorysize); - if (!videomemory) { - ret = -ENOMEM; - goto err_irq; - } - - info->screen_base = (char *)videomemory; - info->fix.smem_len = videomemorysize; - - info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB; - info->fbops = &auok190xfb_ops; - - ret = auok190xfb_check_var(&info->var, info); - if (ret) - goto err_defio; - - auok190xfb_set_fix(info); - - /* deferred io init */ - - info->fbdefio = devm_kzalloc(info->device, - sizeof(struct fb_deferred_io), - GFP_KERNEL); - if (!info->fbdefio) { - ret = -ENOMEM; - goto err_defio; - } - - dev_dbg(info->device, "targeting %d frames per second\n", board->fps); - info->fbdefio->delay = HZ / board->fps; - info->fbdefio->first_io = auok190xfb_dpy_first_io, - info->fbdefio->deferred_io = auok190xfb_dpy_deferred_io, - fb_deferred_io_init(info); - - /* color map */ - - ret = fb_alloc_cmap(&info->cmap, 256, 0); - if (ret < 0) { - dev_err(info->device, "Failed to allocate colormap\n"); - goto err_cmap; - } - - /* controller init */ - - par->consecutive_threshold = 100; - par->init(par); - auok190x_identify(par); - - platform_set_drvdata(pdev, info); - - ret = register_framebuffer(info); - if (ret < 0) - goto err_regfb; - - ret = sysfs_create_group(&info->device->kobj, &auok190x_attr_group); - if (ret) - goto err_sysfs; - - dev_info(info->device, "fb%d: %dx%d using %dK of video memory\n", - info->node, info->var.xres, info->var.yres, - videomemorysize >> 10); - - /* increase autosuspend_delay when we use alternative methods - * for runtime_pm - */ - par->autosuspend_delay = (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) - ? 1000 : 200; - - pm_runtime_set_active(info->device); - pm_runtime_enable(info->device); - pm_runtime_set_autosuspend_delay(info->device, par->autosuspend_delay); - pm_runtime_use_autosuspend(info->device); - - return 0; - -err_sysfs: - unregister_framebuffer(info); -err_regfb: - fb_dealloc_cmap(&info->cmap); -err_cmap: - fb_deferred_io_cleanup(info); -err_defio: - vfree((void *)info->screen_base); -err_irq: - auok190x_power(par, 0); -err_gpio3: - gpio_free(board->gpio_nrst); -err_gpio2: - gpio_free(board->gpio_nsleep); -err_gpio1: - board->cleanup(par); -err_board: - regulator_put(par->regulator); -err_reg: - framebuffer_release(info); - - return ret; -} -EXPORT_SYMBOL_GPL(auok190x_common_probe); - -int auok190x_common_remove(struct platform_device *pdev) -{ - struct fb_info *info = platform_get_drvdata(pdev); - struct auok190xfb_par *par = info->par; - struct auok190x_board *board = par->board; - - pm_runtime_disable(info->device); - - sysfs_remove_group(&info->device->kobj, &auok190x_attr_group); - - unregister_framebuffer(info); - - fb_dealloc_cmap(&info->cmap); - - fb_deferred_io_cleanup(info); - - vfree((void *)info->screen_base); - - auok190x_power(par, 0); - - gpio_free(board->gpio_nrst); - gpio_free(board->gpio_nsleep); - - board->cleanup(par); - - regulator_put(par->regulator); - - framebuffer_release(info); - - return 0; -} -EXPORT_SYMBOL_GPL(auok190x_common_remove); - -MODULE_DESCRIPTION("Common code for AUO-K190X controllers"); -MODULE_AUTHOR("Heiko Stuebner <heiko@xxxxxxxxx>"); -MODULE_LICENSE("GPL"); Index: b/drivers/video/fbdev/auo_k190x.h =================================================================== --- a/drivers/video/fbdev/auo_k190x.h 2017-10-18 14:35:21.947448311 +0200 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,129 +0,0 @@ -/* - * Private common definitions for AUO-K190X framebuffer drivers - * - * Copyright (C) 2012 Heiko Stuebner <heiko@xxxxxxxxx> - * - * 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. - */ - -/* - * I80 interface specific defines - */ - -#define AUOK190X_I80_CS 0x01 -#define AUOK190X_I80_DC 0x02 -#define AUOK190X_I80_WR 0x03 -#define AUOK190X_I80_OE 0x04 - -/* - * AUOK190x commands, common to both controllers - */ - -#define AUOK190X_CMD_INIT 0x0000 -#define AUOK190X_CMD_STANDBY 0x0001 -#define AUOK190X_CMD_WAKEUP 0x0002 -#define AUOK190X_CMD_TCON_RESET 0x0003 -#define AUOK190X_CMD_DATA_STOP 0x1002 -#define AUOK190X_CMD_LUT_START 0x1003 -#define AUOK190X_CMD_DISP_REFRESH 0x1004 -#define AUOK190X_CMD_DISP_RESET 0x1005 -#define AUOK190X_CMD_PRE_DISPLAY_START 0x100D -#define AUOK190X_CMD_PRE_DISPLAY_STOP 0x100F -#define AUOK190X_CMD_FLASH_W 0x2000 -#define AUOK190X_CMD_FLASH_E 0x2001 -#define AUOK190X_CMD_FLASH_STS 0x2002 -#define AUOK190X_CMD_FRAMERATE 0x3000 -#define AUOK190X_CMD_READ_VERSION 0x4000 -#define AUOK190X_CMD_READ_STATUS 0x4001 -#define AUOK190X_CMD_READ_LUT 0x4003 -#define AUOK190X_CMD_DRIVERTIMING 0x5000 -#define AUOK190X_CMD_LBALANCE 0x5001 -#define AUOK190X_CMD_AGINGMODE 0x6000 -#define AUOK190X_CMD_AGINGEXIT 0x6001 - -/* - * Common settings for AUOK190X_CMD_INIT - */ - -#define AUOK190X_INIT_DATA_FILTER (0 << 12) -#define AUOK190X_INIT_DATA_BYPASS (1 << 12) -#define AUOK190X_INIT_INVERSE_WHITE (0 << 9) -#define AUOK190X_INIT_INVERSE_BLACK (1 << 9) -#define AUOK190X_INIT_SCAN_DOWN (0 << 1) -#define AUOK190X_INIT_SCAN_UP (1 << 1) -#define AUOK190X_INIT_SHIFT_LEFT (0 << 0) -#define AUOK190X_INIT_SHIFT_RIGHT (1 << 0) - -/* Common bits to pixels - * Mode 15-12 11-8 7-4 3-0 - * format0 4 3 2 1 - * format1 3 4 1 2 - */ - -#define AUOK190X_INIT_FORMAT0 0 -#define AUOK190X_INIT_FORMAT1 (1 << 6) - -/* - * settings for AUOK190X_CMD_RESET - */ - -#define AUOK190X_RESET_TCON (0 << 0) -#define AUOK190X_RESET_NORMAL (1 << 0) -#define AUOK190X_RESET_PON (1 << 1) - -/* - * AUOK190X_CMD_VERSION - */ - -#define AUOK190X_VERSION_TEMP_MASK (0x1ff) -#define AUOK190X_VERSION_EPD_MASK (0xff) -#define AUOK190X_VERSION_SIZE_INT(_val) ((_val & 0xfc00) >> 10) -#define AUOK190X_VERSION_SIZE_FLOAT(_val) ((_val & 0x3c0) >> 6) -#define AUOK190X_VERSION_MODEL(_val) (_val & 0x3f) -#define AUOK190X_VERSION_LUT(_val) (_val & 0xff) -#define AUOK190X_VERSION_TCON(_val) ((_val & 0xff00) >> 8) - -/* - * update modes for CMD_PARTIALDISP on K1900 and CMD_DDMA on K1901 - */ - -#define AUOK190X_UPDATE_MODE(_res) ((_res & 0x7) << 12) -#define AUOK190X_UPDATE_NONFLASH (1 << 15) - -/* - * track panel specific parameters for common init - */ - -struct auok190x_init_data { - char *id; - struct auok190x_board *board; - - void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2); - void (*update_all)(struct auok190xfb_par *par); - bool (*need_refresh)(struct auok190xfb_par *par); - void (*init)(struct auok190xfb_par *par); -}; - - -extern void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data); -extern int auok190x_send_command(struct auok190xfb_par *par, u16 data); -extern void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd, - int argc, u16 *argv); -extern int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd, - int argc, u16 *argv); -extern void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par, - u16 cmd, int argc, u16 *argv, - int size, u16 *data); -extern int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd, - int argc, u16 *argv, int size, - u16 *data); -extern int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd, - int argc, u16 *argv); - -extern int auok190x_common_probe(struct platform_device *pdev, - struct auok190x_init_data *init); -extern int auok190x_common_remove(struct platform_device *pdev); - -extern const struct dev_pm_ops auok190x_pm; Index: b/include/video/auo_k190xfb.h =================================================================== --- a/include/video/auo_k190xfb.h 2017-10-18 14:35:25.827448262 +0200 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,107 +0,0 @@ -/* - * Definitions for AUO-K190X framebuffer drivers - * - * Copyright (C) 2012 Heiko Stuebner <heiko@xxxxxxxxx> - * - * 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. - */ - -#ifndef _LINUX_VIDEO_AUO_K190XFB_H_ -#define _LINUX_VIDEO_AUO_K190XFB_H_ - -/* Controller standby command needs a param */ -#define AUOK190X_QUIRK_STANDBYPARAM (1 << 0) - -/* Controller standby is completely broken */ -#define AUOK190X_QUIRK_STANDBYBROKEN (1 << 1) - -/* - * Resolutions for the displays - */ -#define AUOK190X_RESOLUTION_800_600 0 -#define AUOK190X_RESOLUTION_1024_768 1 -#define AUOK190X_RESOLUTION_600_800 4 -#define AUOK190X_RESOLUTION_768_1024 5 - -/* - * struct used by auok190x. board specific stuff comes from *board - */ -struct auok190xfb_par { - struct fb_info *info; - struct auok190x_board *board; - - struct regulator *regulator; - - struct mutex io_lock; - struct delayed_work work; - wait_queue_head_t waitq; - int resolution; - int rotation; - int consecutive_threshold; - int update_cnt; - - /* panel and controller informations */ - int epd_type; - int panel_size_int; - int panel_size_float; - int panel_model; - int tcon_version; - int lut_version; - - /* individual controller callbacks */ - void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2); - void (*update_all)(struct auok190xfb_par *par); - bool (*need_refresh)(struct auok190xfb_par *par); - void (*init)(struct auok190xfb_par *par); - void (*recover)(struct auok190xfb_par *par); - - int update_mode; /* mode to use for updates */ - int last_mode; /* update mode last used */ - int flash; - - /* power management */ - int autosuspend_delay; - bool standby; - bool manual_standby; -}; - -/** - * Board specific platform-data - * @init: initialize the controller interface - * @cleanup: cleanup the controller interface - * @wait_for_rdy: wait until the controller is not busy anymore - * @set_ctl: change an interface control - * @set_hdb: write a value to the data register - * @get_hdb: read a value from the data register - * @setup_irq: method to setup the irq handling on the busy gpio - * @gpio_nsleep: sleep gpio - * @gpio_nrst: reset gpio - * @gpio_nbusy: busy gpio - * @resolution: one of the AUOK190X_RESOLUTION constants - * @rotation: rotation of the framebuffer - * @quirks: controller quirks to honor - * @fps: frames per second for defio - */ -struct auok190x_board { - int (*init)(struct auok190xfb_par *); - void (*cleanup)(struct auok190xfb_par *); - int (*wait_for_rdy)(struct auok190xfb_par *); - - void (*set_ctl)(struct auok190xfb_par *, unsigned char, u8); - void (*set_hdb)(struct auok190xfb_par *, u16); - u16 (*get_hdb)(struct auok190xfb_par *); - - int (*setup_irq)(struct fb_info *); - - int gpio_nsleep; - int gpio_nrst; - int gpio_nbusy; - - int resolution; - int quirks; - int fps; -}; - -#endif _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel