1/****************************************************************************** 2 3 ProjectName: FBTFT driver ***** ***** 4 for the RA8875 LCD Controller * * ************ 5 * ** ** * * 6 Copyright � by Pf@nne & NOTRO * * * * * **** * 7 * * * * * * * 8 Last modification by: * * * * **** * 9 - Pf@nne (pf@nne-mail.de) * * ***** * 10 * * * ******* 11 ***** * * 12 Date : 10.06.2014 * * 13 Version : V1.13 ***** 14 Revision : 5 15 16******************************************************************************* 17 * This program is free software; you can redistribute it and/or modify 18 * it under the terms of the GNU General Public License as published by 19 * the Free Software Foundation; either version 2 of the License, or 20 * (at your option) any later version. 21 * 22 * This program is distributed in the hope that it will be useful, 23 * but WITHOUT ANY WARRANTY; without even the implied warranty of 24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 25 * GNU General Public License for more details. 26 * 27 * You should have received a copy of the GNU General Public License 28 * along with this program; if not, write to the Free Software 29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 30 */ 31 32#include <linux/module.h> 33#include <linux/kernel.h> 34#include <linux/init.h> 35#include <linux/delay.h> 36 37#include <linux/gpio.h> 38#include "fbtft.h" 39 40#define DRVNAME "fb_ra8875" 41 42static int write_spi(struct fbtft_par *par, void *buf, size_t len) 43{ 44 struct spi_transfer t = { 45 .tx_buf = buf, 46 .len = len, 47 .speed_hz = 1000000, 48 }; 49 struct spi_message m; 50 51 fbtft_par_dbg_hex(DEBUG_WRITE, par, par->info->device, u8, buf, len, 52 "%s(len=%d): ", __func__, len); 53 54 if (!par->spi) { 55 dev_err(par->info->device, 56 "%s: par->spi is unexpectedly NULL\n", __func__); 57 return -1; 58 } 59 60 spi_message_init(&m); 61 if (par->txbuf.dma && buf == par->txbuf.buf) { 62 t.tx_dma = par->txbuf.dma; 63 m.is_dma_mapped = 1; 64 } 65 spi_message_add_tail(&t, &m); 66 return spi_sync(par->spi, &m); 67} 68 69static int init_display(struct fbtft_par *par) 70{ 71 gpio_set_value(par->gpio.dc, 1); 72 73 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, 74 "%s()\n", __func__); 75 fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, 76 "display size %dx%d\n", par->info->var.xres, par->info->var.yres); 77 78 par->fbtftops.reset(par); 79 80 if ((par->info->var.xres == 320) && (par->info->var.yres == 240)) { 81 /* PLL clock frequency */ 82 write_reg(par, 0x88, 0x0A); 83 write_reg(par, 0x89, 0x02); 84 mdelay(10); 85 /* color deep / MCU Interface */ 86 write_reg(par, 0x10, 0x0C); 87 /* pixel clock period */ 88 write_reg(par, 0x04, 0x03); 89 mdelay(1); 90 /* horizontal settings */ 91 write_reg(par, 0x14, 0x27); 92 write_reg(par, 0x15, 0x00); 93 write_reg(par, 0x16, 0x05); 94 write_reg(par, 0x17, 0x04); 95 write_reg(par, 0x18, 0x03); 96 /* vertical settings */ 97 write_reg(par, 0x19, 0xEF); 98 write_reg(par, 0x1A, 0x00); 99 write_reg(par, 0x1B, 0x05); 100 write_reg(par, 0x1C, 0x00); 101 write_reg(par, 0x1D, 0x0E); 102 write_reg(par, 0x1E, 0x00); 103 write_reg(par, 0x1F, 0x02); 104 } else if ((par->info->var.xres == 480) && (par->info->var.yres == 272)) { 105 /* PLL clock frequency */ 106 write_reg(par, 0x88, 0x0A); 107 write_reg(par, 0x89, 0x02); 108 mdelay(10); 109 /* color deep / MCU Interface */ 110 write_reg(par, 0x10, 0x0C); 111 /* pixel clock period */ 112 write_reg(par, 0x04, 0x82); 113 mdelay(1); 114 /* horizontal settings */ 115 write_reg(par, 0x14, 0x3B); 116 write_reg(par, 0x15, 0x00); 117 write_reg(par, 0x16, 0x01); 118 write_reg(par, 0x17, 0x00); 119 write_reg(par, 0x18, 0x05); 120 /* vertical settings */ 121 write_reg(par, 0x19, 0x0F); 122 write_reg(par, 0x1A, 0x01); 123 write_reg(par, 0x1B, 0x02); 124 write_reg(par, 0x1C, 0x00); 125 write_reg(par, 0x1D, 0x07); 126 write_reg(par, 0x1E, 0x00); 127 write_reg(par, 0x1F, 0x09); 128 } else if ((par->info->var.xres == 640) && (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, 0x01); 137 mdelay(1); 138 /* horizontal settings */ 139 write_reg(par, 0x14, 0x4F); 140 write_reg(par, 0x15, 0x05); 141 write_reg(par, 0x16, 0x0F); 142 write_reg(par, 0x17, 0x01); 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, 0x0A); 148 write_reg(par, 0x1C, 0x00); 149 write_reg(par, 0x1D, 0x0E); 150 write_reg(par, 0x1E, 0x00); 151 write_reg(par, 0x1F, 0x01); 152 } else if ((par->info->var.xres == 800) && (par->info->var.yres == 480)) { 153 /* PLL clock frequency */ 154 write_reg(par, 0x88, 0x0B); 155 write_reg(par, 0x89, 0x02); 156 mdelay(10); 157 /* color deep / MCU Interface */ 158 write_reg(par, 0x10, 0x0C); 159 /* pixel clock period */ 160 write_reg(par, 0x04, 0x81); 161 mdelay(1); 162 /* horizontal settings */ 163 write_reg(par, 0x14, 0x63); 164 write_reg(par, 0x15, 0x03); 165 write_reg(par, 0x16, 0x03); 166 write_reg(par, 0x17, 0x02); 167 write_reg(par, 0x18, 0x00); 168 /* vertical settings */ 169 write_reg(par, 0x19, 0xDF); 170 write_reg(par, 0x1A, 0x01); 171 write_reg(par, 0x1B, 0x14); 172 write_reg(par, 0x1C, 0x00); 173 write_reg(par, 0x1D, 0x06); 174 write_reg(par, 0x1E, 0x00); 175 write_reg(par, 0x1F, 0x01); 176 } else { 177 dev_err(par->info->device, "display size is not supported!!"); 178 return -1; 179 } 180 181 /* PWM clock */ 182 write_reg(par, 0x8a, 0x81); 183 write_reg(par, 0x8b, 0xFF); 184 mdelay(10); 185 186 /* Display ON */ 187 write_reg(par, 0x01, 0x80); 188 mdelay(10); 189 190 return 0; 191} 192 193static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) 194{ 195 fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, 196 "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n", __func__, xs, ys, xe, ye); 197 198 /* Set_Active_Window */ 199 write_reg(par, 0x30, xs & 0x00FF); 200 write_reg(par, 0x31, (xs & 0xFF00) >> 8); 201 write_reg(par, 0x32, ys & 0x00FF); 202 write_reg(par, 0x33, (ys & 0xFF00) >> 8); 203 write_reg(par, 0x34, (xs+xe) & 0x00FF); 204 write_reg(par, 0x35, ((xs+xe) & 0xFF00) >> 8); 205 write_reg(par, 0x36, (ys+ye) & 0x00FF); 206 write_reg(par, 0x37, ((ys+ye) & 0xFF00) >> 8); 207 208 /* Set_Memory_Write_Cursor */ 209 write_reg(par, 0x46, xs & 0xff); 210 write_reg(par, 0x47, (xs >> 8) & 0x03); 211 write_reg(par, 0x48, ys & 0xff); 212 write_reg(par, 0x49, (ys >> 8) & 0x01); 213 214 write_reg(par, 0x02); 215} 216 217static void write_reg8_bus8(struct fbtft_par *par, int len, ...) 218{ 219 va_list args; 220 int i, ret; 221 u8 *buf = (u8 *)par->buf; 222 223 /* slow down spi-speed for writing registers */ 224 par->fbtftops.write = write_spi; 225 226 if (unlikely(par->debug & DEBUG_WRITE_REGISTER)) { 227 va_start(args, len); 228 for (i = 0; i < len; i++) 229 buf[i] = (u8)va_arg(args, unsigned int); 230 va_end(args); 231 fbtft_par_dbg_hex(DEBUG_WRITE_REGISTER, par, par->info->device, 232 u8, buf, len, "%s: ", __func__); 233 } 234 235 va_start(args, len); 236 *buf++ = 0x80; 237 *buf = (u8)va_arg(args, unsigned int); 238 ret = par->fbtftops.write(par, par->buf, 2); 239 if (ret < 0) { 240 va_end(args); 241 dev_err(par->info->device, "write() failed and returned %dn", 242 ret); 243 return; 244 } 245 len--; 246 247 udelay(100); 248 249 if (len) { 250 buf = (u8 *)par->buf; 251 *buf++ = 0x00; 252 i = len; 253 while (i--) 254 *buf++ = (u8)va_arg(args, unsigned int); 255 256 ret = par->fbtftops.write(par, par->buf, len + 1); 257 if (ret < 0) { 258 va_end(args); 259 dev_err(par->info->device, 260 "write() failed and returned %dn", ret); 261 return; 262 } 263 } 264 va_end(args); 265 266 /* restore user spi-speed */ 267 par->fbtftops.write = fbtft_write_spi; 268 udelay(100); 269} 270 271static int write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) 272{ 273 u16 *vmem16; 274 u16 *txbuf16 = (u16 *)par->txbuf.buf; 275 size_t remain; 276 size_t to_copy; 277 size_t tx_array_size; 278 int i; 279 int ret = 0; 280 size_t startbyte_size = 0; 281 282 fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s(offset=%zu, len=%zu)\n", 283 __func__, offset, len); 284 285 remain = len / 2; 286 vmem16 = (u16 *)(par->info->screen_base + offset); 287 tx_array_size = par->txbuf.len / 2; 288 txbuf16 = (u16 *)(par->txbuf.buf + 1); 289 tx_array_size -= 2; 290 *(u8 *)(par->txbuf.buf) = 0x00; 291 startbyte_size = 1; 292 293 while (remain) { 294 to_copy = remain > tx_array_size ? tx_array_size : remain; 295 dev_dbg(par->info->device, " to_copy=%zu, remain=%zu\n", 296 to_copy, remain - to_copy); 297 298 for (i = 0; i < to_copy; i++) 299 txbuf16[i] = cpu_to_be16(vmem16[i]); 300 301 vmem16 = vmem16 + to_copy; 302 ret = par->fbtftops.write(par, par->txbuf.buf, 303 startbyte_size + to_copy * 2); 304 if (ret < 0) 305 return ret; 306 remain -= to_copy; 307 } 308 309 return ret; 310} 311 312static struct fbtft_display display = { 313 .regwidth = 8, 314 .fbtftops = { 315 .init_display = init_display, 316 .set_addr_win = set_addr_win, 317 .write_register = write_reg8_bus8, 318 .write_vmem = write_vmem16_bus8, 319 .write = write_spi, 320 }, 321}; 322FBTFT_REGISTER_DRIVER(DRVNAME, "raio,ra8875", &display); 323 324MODULE_ALIAS("spi:" DRVNAME); 325MODULE_ALIAS("platform:" DRVNAME); 326MODULE_ALIAS("spi:ra8875"); 327MODULE_ALIAS("platform:ra8875"); 328 329MODULE_DESCRIPTION("FB driver for the RA8875 LCD Controller"); 330MODULE_AUTHOR("Pf@nne"); 331MODULE_LICENSE("GPL"); 332