File Index
Files and directories
Sign in
FILE

fb_uc1701.c

File preview with syntax highlighting.

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