Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | // SPDX-License-Identifier: GPL-2.0+ /* * FB driver for the UC1701 LCD Controller * * The display is monochrome and the video memory is RGB565. * Any pixel value except 0 turns the pixel on. * * Copyright (C) 2014 Juergen Holzmann */ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/gpio/consumer.h> #include <linux/spi/spi.h> #include <linux/delay.h> #include "fbtft.h" #define DRVNAME "fb_uc1701" #define WIDTH 102 #define HEIGHT 64 #define PAGES (HEIGHT / 8) /* 1: Display on/off */ #define LCD_DISPLAY_ENABLE 0xAE /* 2: display start line set */ #define LCD_START_LINE 0x40 /* 3: Page address set (lower 4 bits select one of the pages) */ #define LCD_PAGE_ADDRESS 0xB0 /* 4: column address */ #define LCD_COL_ADDRESS 0x10 /* 8: select orientation */ #define LCD_BOTTOMVIEW 0xA0 /* 9: inverted display */ #define LCD_DISPLAY_INVERT 0xA6 /* 10: show memory content or switch all pixels on */ #define LCD_ALL_PIXEL 0xA4 /* 11: lcd bias set */ #define LCD_BIAS 0xA2 /* 14: Reset Controller */ #define LCD_RESET_CMD 0xE2 /* 15: output mode select (turns display upside-down) */ #define LCD_SCAN_DIR 0xC0 /* 16: power control set */ #define LCD_POWER_CONTROL 0x28 /* 17: voltage regulator resistor ratio set */ #define LCD_VOLTAGE 0x20 /* 18: Volume mode set */ #define LCD_VOLUME_MODE 0x81 /* 22: NOP command */ #define LCD_NO_OP 0xE3 /* 25: advanced program control */ #define LCD_ADV_PROG_CTRL 0xFA /* 25: advanced program control2 */ #define LCD_ADV_PROG_CTRL2 0x10 #define LCD_TEMPCOMP_HIGH 0x80 /* column offset for normal orientation */ #define SHIFT_ADDR_NORMAL 0 /* column offset for bottom view orientation */ #define SHIFT_ADDR_TOPVIEW 30 static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); /* softreset of LCD */ write_reg(par, LCD_RESET_CMD); mdelay(10); /* set startpoint */ write_reg(par, LCD_START_LINE); /* select orientation BOTTOMVIEW */ write_reg(par, LCD_BOTTOMVIEW | 1); /* output mode select (turns display upside-down) */ write_reg(par, LCD_SCAN_DIR | 0x00); /* Normal Pixel mode */ write_reg(par, LCD_ALL_PIXEL | 0); /* positive display */ write_reg(par, LCD_DISPLAY_INVERT | 0); /* bias 1/9 */ write_reg(par, LCD_BIAS | 0); /* power control mode: all features on */ write_reg(par, LCD_POWER_CONTROL | 0x07); /* set voltage regulator R/R */ write_reg(par, LCD_VOLTAGE | 0x07); /* volume mode set */ write_reg(par, LCD_VOLUME_MODE); write_reg(par, 0x09); write_reg(par, LCD_NO_OP); /* advanced program control */ write_reg(par, LCD_ADV_PROG_CTRL); write_reg(par, LCD_ADV_PROG_CTRL2 | LCD_TEMPCOMP_HIGH); /* enable display */ write_reg(par, LCD_DISPLAY_ENABLE | 1); return 0; } static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye) { /* goto address */ write_reg(par, LCD_PAGE_ADDRESS); write_reg(par, 0x00); write_reg(par, LCD_COL_ADDRESS); } static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) { u16 *vmem16 = (u16 *)par->info->screen_buffer; u8 *buf; int x, y, i; int ret = 0; for (y = 0; y < PAGES; y++) { buf = par->txbuf.buf; for (x = 0; x < WIDTH; x++) { *buf = 0x00; for (i = 0; i < 8; i++) *buf |= (vmem16[((y * 8 * WIDTH) + (i * WIDTH)) + x] ? 1 : 0) << i; buf++; } write_reg(par, LCD_PAGE_ADDRESS | (u8)y); write_reg(par, 0x00); write_reg(par, LCD_COL_ADDRESS); gpiod_set_value(par->gpio.dc, 1); ret = par->fbtftops.write(par, par->txbuf.buf, WIDTH); gpiod_set_value(par->gpio.dc, 0); } if (ret < 0) dev_err(par->info->device, "write failed and returned: %d\n", ret); return ret; } static struct fbtft_display display = { .regwidth = 8, .width = WIDTH, .height = HEIGHT, .fbtftops = { .init_display = init_display, .set_addr_win = set_addr_win, .write_vmem = write_vmem, }, .backlight = 1, }; FBTFT_REGISTER_DRIVER(DRVNAME, "UltraChip,uc1701", &display); MODULE_ALIAS("spi:" DRVNAME); MODULE_ALIAS("spi:uc1701"); MODULE_DESCRIPTION("FB driver for the UC1701 LCD Controller"); MODULE_AUTHOR("Juergen Holzmann"); MODULE_LICENSE("GPL"); |