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");