cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fb_ra8875.c (7561B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * FBTFT driver for the RA8875 LCD Controller
      4 * Copyright by Pf@nne & NOTRO
      5 */
      6
      7#include <linux/module.h>
      8#include <linux/kernel.h>
      9#include <linux/init.h>
     10#include <linux/delay.h>
     11
     12#include <linux/gpio/consumer.h>
     13#include "fbtft.h"
     14
     15#define DRVNAME "fb_ra8875"
     16
     17static int write_spi(struct fbtft_par *par, void *buf, size_t len)
     18{
     19	struct spi_transfer t = {
     20		.tx_buf = buf,
     21		.len = len,
     22		.speed_hz = 1000000,
     23	};
     24	struct spi_message m;
     25
     26	fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len,
     27			  "%s(len=%zu): ", __func__, len);
     28
     29	if (!par->spi) {
     30		dev_err(par->info->device,
     31			"%s: par->spi is unexpectedly NULL\n", __func__);
     32		return -1;
     33	}
     34
     35	spi_message_init(&m);
     36	spi_message_add_tail(&t, &m);
     37	return spi_sync(par->spi, &m);
     38}
     39
     40static int init_display(struct fbtft_par *par)
     41{
     42	gpiod_set_value(par->gpio.dc, 1);
     43
     44	fbtft_par_dbg(DEBUG_INIT_DISPLAY, par,
     45		      "%s()\n", __func__);
     46	fbtft_par_dbg(DEBUG_INIT_DISPLAY, par,
     47		      "display size %dx%d\n",
     48		par->info->var.xres,
     49		par->info->var.yres);
     50
     51	par->fbtftops.reset(par);
     52
     53	if ((par->info->var.xres == 320) && (par->info->var.yres == 240)) {
     54		/* PLL clock frequency */
     55		write_reg(par, 0x88, 0x0A);
     56		write_reg(par, 0x89, 0x02);
     57		mdelay(10);
     58		/* color deep / MCU Interface */
     59		write_reg(par, 0x10, 0x0C);
     60		/* pixel clock period  */
     61		write_reg(par, 0x04, 0x03);
     62		mdelay(1);
     63		/* horizontal settings */
     64		write_reg(par, 0x14, 0x27);
     65		write_reg(par, 0x15, 0x00);
     66		write_reg(par, 0x16, 0x05);
     67		write_reg(par, 0x17, 0x04);
     68		write_reg(par, 0x18, 0x03);
     69		/* vertical settings */
     70		write_reg(par, 0x19, 0xEF);
     71		write_reg(par, 0x1A, 0x00);
     72		write_reg(par, 0x1B, 0x05);
     73		write_reg(par, 0x1C, 0x00);
     74		write_reg(par, 0x1D, 0x0E);
     75		write_reg(par, 0x1E, 0x00);
     76		write_reg(par, 0x1F, 0x02);
     77	} else if ((par->info->var.xres == 480) &&
     78		   (par->info->var.yres == 272)) {
     79		/* PLL clock frequency  */
     80		write_reg(par, 0x88, 0x0A);
     81		write_reg(par, 0x89, 0x02);
     82		mdelay(10);
     83		/* color deep / MCU Interface */
     84		write_reg(par, 0x10, 0x0C);
     85		/* pixel clock period  */
     86		write_reg(par, 0x04, 0x82);
     87		mdelay(1);
     88		/* horizontal settings */
     89		write_reg(par, 0x14, 0x3B);
     90		write_reg(par, 0x15, 0x00);
     91		write_reg(par, 0x16, 0x01);
     92		write_reg(par, 0x17, 0x00);
     93		write_reg(par, 0x18, 0x05);
     94		/* vertical settings */
     95		write_reg(par, 0x19, 0x0F);
     96		write_reg(par, 0x1A, 0x01);
     97		write_reg(par, 0x1B, 0x02);
     98		write_reg(par, 0x1C, 0x00);
     99		write_reg(par, 0x1D, 0x07);
    100		write_reg(par, 0x1E, 0x00);
    101		write_reg(par, 0x1F, 0x09);
    102	} else if ((par->info->var.xres == 640) &&
    103		   (par->info->var.yres == 480)) {
    104		/* PLL clock frequency */
    105		write_reg(par, 0x88, 0x0B);
    106		write_reg(par, 0x89, 0x02);
    107		mdelay(10);
    108		/* color deep / MCU Interface */
    109		write_reg(par, 0x10, 0x0C);
    110		/* pixel clock period */
    111		write_reg(par, 0x04, 0x01);
    112		mdelay(1);
    113		/* horizontal settings */
    114		write_reg(par, 0x14, 0x4F);
    115		write_reg(par, 0x15, 0x05);
    116		write_reg(par, 0x16, 0x0F);
    117		write_reg(par, 0x17, 0x01);
    118		write_reg(par, 0x18, 0x00);
    119		/* vertical settings */
    120		write_reg(par, 0x19, 0xDF);
    121		write_reg(par, 0x1A, 0x01);
    122		write_reg(par, 0x1B, 0x0A);
    123		write_reg(par, 0x1C, 0x00);
    124		write_reg(par, 0x1D, 0x0E);
    125		write_reg(par, 0x1E, 0x00);
    126		write_reg(par, 0x1F, 0x01);
    127	} else if ((par->info->var.xres == 800) &&
    128		   (par->info->var.yres == 480)) {
    129		/* PLL clock frequency */
    130		write_reg(par, 0x88, 0x0B);
    131		write_reg(par, 0x89, 0x02);
    132		mdelay(10);
    133		/* color deep / MCU Interface */
    134		write_reg(par, 0x10, 0x0C);
    135		/* pixel clock period */
    136		write_reg(par, 0x04, 0x81);
    137		mdelay(1);
    138		/* horizontal settings */
    139		write_reg(par, 0x14, 0x63);
    140		write_reg(par, 0x15, 0x03);
    141		write_reg(par, 0x16, 0x03);
    142		write_reg(par, 0x17, 0x02);
    143		write_reg(par, 0x18, 0x00);
    144		/* vertical settings */
    145		write_reg(par, 0x19, 0xDF);
    146		write_reg(par, 0x1A, 0x01);
    147		write_reg(par, 0x1B, 0x14);
    148		write_reg(par, 0x1C, 0x00);
    149		write_reg(par, 0x1D, 0x06);
    150		write_reg(par, 0x1E, 0x00);
    151		write_reg(par, 0x1F, 0x01);
    152	} else {
    153		dev_err(par->info->device, "display size is not supported!!");
    154		return -1;
    155	}
    156
    157	/* PWM clock */
    158	write_reg(par, 0x8a, 0x81);
    159	write_reg(par, 0x8b, 0xFF);
    160	mdelay(10);
    161
    162	/* Display ON */
    163	write_reg(par, 0x01, 0x80);
    164	mdelay(10);
    165
    166	return 0;
    167}
    168
    169static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
    170{
    171	/* Set_Active_Window */
    172	write_reg(par, 0x30, xs & 0x00FF);
    173	write_reg(par, 0x31, (xs & 0xFF00) >> 8);
    174	write_reg(par, 0x32, ys & 0x00FF);
    175	write_reg(par, 0x33, (ys & 0xFF00) >> 8);
    176	write_reg(par, 0x34, (xs + xe) & 0x00FF);
    177	write_reg(par, 0x35, ((xs + xe) & 0xFF00) >> 8);
    178	write_reg(par, 0x36, (ys + ye) & 0x00FF);
    179	write_reg(par, 0x37, ((ys + ye) & 0xFF00) >> 8);
    180
    181	/* Set_Memory_Write_Cursor */
    182	write_reg(par, 0x46,  xs & 0xff);
    183	write_reg(par, 0x47, (xs >> 8) & 0x03);
    184	write_reg(par, 0x48,  ys & 0xff);
    185	write_reg(par, 0x49, (ys >> 8) & 0x01);
    186
    187	write_reg(par, 0x02);
    188}
    189
    190static void write_reg8_bus8(struct fbtft_par *par, int len, ...)
    191{
    192	va_list args;
    193	int i, ret;
    194	u8 *buf = par->buf;
    195
    196	/* slow down spi-speed for writing registers */
    197	par->fbtftops.write = write_spi;
    198
    199	if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) {
    200		va_start(args, len);
    201		for (i = 0; i < len; i++)
    202			buf[i] = (u8)va_arg(args, unsigned int);
    203		va_end(args);
    204		fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device,
    205				  u8, buf, len, "%s: ", __func__);
    206	}
    207
    208	va_start(args, len);
    209	*buf++ = 0x80;
    210	*buf = (u8)va_arg(args, unsigned int);
    211	ret = par->fbtftops.write(par, par->buf, 2);
    212	if (ret < 0) {
    213		va_end(args);
    214		dev_err(par->info->device, "write() failed and returned %dn",
    215			ret);
    216		return;
    217	}
    218	len--;
    219
    220	udelay(100);
    221
    222	if (len) {
    223		buf = (u8 *)par->buf;
    224		*buf++ = 0x00;
    225		i = len;
    226		while (i--)
    227			*buf++ = (u8)va_arg(args, unsigned int);
    228
    229		ret = par->fbtftops.write(par, par->buf, len + 1);
    230		if (ret < 0) {
    231			va_end(args);
    232			dev_err(par->info->device,
    233				"write() failed and returned %dn", ret);
    234			return;
    235		}
    236	}
    237	va_end(args);
    238
    239	/* restore user spi-speed */
    240	par->fbtftops.write = fbtft_write_spi;
    241	udelay(100);
    242}
    243
    244static int write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len)
    245{
    246	u16 *vmem16;
    247	__be16 *txbuf16;
    248	size_t remain;
    249	size_t to_copy;
    250	size_t tx_array_size;
    251	int i;
    252	int ret = 0;
    253	size_t startbyte_size = 0;
    254
    255	fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n",
    256		      __func__, offset, len);
    257
    258	remain = len / 2;
    259	vmem16 = (u16 *)(par->info->screen_buffer + offset);
    260	tx_array_size = par->txbuf.len / 2;
    261	txbuf16 = par->txbuf.buf + 1;
    262	tx_array_size -= 2;
    263	*(u8 *)(par->txbuf.buf) = 0x00;
    264	startbyte_size = 1;
    265
    266	while (remain) {
    267		to_copy = min(tx_array_size, remain);
    268		dev_dbg(par->info->device, "    to_copy=%zu, remain=%zu\n",
    269			to_copy, remain - to_copy);
    270
    271		for (i = 0; i < to_copy; i++)
    272			txbuf16[i] = cpu_to_be16(vmem16[i]);
    273
    274		vmem16 = vmem16 + to_copy;
    275		ret = par->fbtftops.write(par, par->txbuf.buf,
    276			startbyte_size + to_copy * 2);
    277		if (ret < 0)
    278			return ret;
    279		remain -= to_copy;
    280	}
    281
    282	return ret;
    283}
    284
    285static struct fbtft_display display = {
    286	.regwidth = 8,
    287	.fbtftops = {
    288		.init_display = init_display,
    289		.set_addr_win = set_addr_win,
    290		.write_register = write_reg8_bus8,
    291		.write_vmem = write_vmem16_bus8,
    292		.write = write_spi,
    293	},
    294};
    295
    296FBTFT_REGISTER_DRIVER(DRVNAME, "raio,ra8875", &display);
    297
    298MODULE_ALIAS("spi:" DRVNAME);
    299MODULE_ALIAS("platform:" DRVNAME);
    300MODULE_ALIAS("spi:ra8875");
    301MODULE_ALIAS("platform:ra8875");
    302
    303MODULE_DESCRIPTION("FB driver for the RA8875 LCD Controller");
    304MODULE_AUTHOR("Pf@nne");
    305MODULE_LICENSE("GPL");