brintos

brintos / linux-shallow public Read only

0
0
Text · 7.0 KiB · efe52fa Raw
252 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Driver for ORISE Technology OTM3225A SOC for TFT LCD3 * Copyright (C) 2017, EETS GmbH, Felix Brack <fb@ltec.ch>4 *5 * This driver implements a lcd device for the ORISE OTM3225A display6 * controller. The control interface to the display is SPI and the display's7 * memory is updated over the 16-bit RGB interface.8 * The main source of information for writing this driver was provided by the9 * OTM3225A datasheet from ORISE Technology. Some information arise from the10 * ILI9328 datasheet from ILITEK as well as from the datasheets and sample code11 * provided by Crystalfontz America Inc. who sells the CFAF240320A-032T, a 3.2"12 * TFT LC display using the OTM3225A controller.13 */14 15#include <linux/delay.h>16#include <linux/device.h>17#include <linux/kernel.h>18#include <linux/lcd.h>19#include <linux/module.h>20#include <linux/spi/spi.h>21 22#define OTM3225A_INDEX_REG	0x7023#define OTM3225A_DATA_REG	0x7224 25/* instruction register list */26#define DRIVER_OUTPUT_CTRL_1	0x0127#define DRIVER_WAVEFORM_CTRL	0x0228#define ENTRY_MODE		0x0329#define SCALING_CTRL		0x0430#define DISPLAY_CTRL_1		0x0731#define DISPLAY_CTRL_2		0x0832#define DISPLAY_CTRL_3		0x0933#define FRAME_CYCLE_CTRL	0x0A34#define EXT_DISP_IFACE_CTRL_1	0x0C35#define FRAME_MAKER_POS		0x0D36#define EXT_DISP_IFACE_CTRL_2	0x0F37#define POWER_CTRL_1		0x1038#define POWER_CTRL_2		0x1139#define POWER_CTRL_3		0x1240#define POWER_CTRL_4		0x1341#define GRAM_ADDR_HORIZ_SET	0x2042#define GRAM_ADDR_VERT_SET	0x2143#define GRAM_READ_WRITE		0x2244#define POWER_CTRL_7		0x2945#define FRAME_RATE_CTRL		0x2B46#define GAMMA_CTRL_1		0x3047#define GAMMA_CTRL_2		0x3148#define GAMMA_CTRL_3		0x3249#define GAMMA_CTRL_4		0x3550#define GAMMA_CTRL_5		0x3651#define GAMMA_CTRL_6		0x3752#define GAMMA_CTRL_7		0x3853#define GAMMA_CTRL_8		0x3954#define GAMMA_CTRL_9		0x3C55#define GAMMA_CTRL_10		0x3D56#define WINDOW_HORIZ_RAM_START	0x5057#define WINDOW_HORIZ_RAM_END	0x5158#define WINDOW_VERT_RAM_START	0x5259#define WINDOW_VERT_RAM_END	0x5360#define DRIVER_OUTPUT_CTRL_2	0x6061#define BASE_IMG_DISPLAY_CTRL	0x6162#define VERT_SCROLL_CTRL	0x6A63#define PD1_DISPLAY_POS		0x8064#define PD1_RAM_START		0x8165#define PD1_RAM_END		0x8266#define PD2_DISPLAY_POS		0x8367#define PD2_RAM_START		0x8468#define PD2_RAM_END		0x8569#define PANEL_IFACE_CTRL_1	0x9070#define PANEL_IFACE_CTRL_2	0x9271#define PANEL_IFACE_CTRL_4	0x9572#define PANEL_IFACE_CTRL_5	0x9773 74struct otm3225a_data {75	struct spi_device *spi;76	struct lcd_device *ld;77	int power;78};79 80struct otm3225a_spi_instruction {81	unsigned char reg;	/* register to write */82	unsigned short value;	/* data to write to 'reg' */83	unsigned short delay;	/* delay in ms after write */84};85 86static struct otm3225a_spi_instruction display_init[] = {87	{ DRIVER_OUTPUT_CTRL_1,		0x0000, 0 },88	{ DRIVER_WAVEFORM_CTRL,		0x0700, 0 },89	{ ENTRY_MODE,			0x50A0, 0 },90	{ SCALING_CTRL,			0x0000, 0 },91	{ DISPLAY_CTRL_2,		0x0606, 0 },92	{ DISPLAY_CTRL_3,		0x0000, 0 },93	{ FRAME_CYCLE_CTRL,		0x0000, 0 },94	{ EXT_DISP_IFACE_CTRL_1,	0x0000, 0 },95	{ FRAME_MAKER_POS,		0x0000, 0 },96	{ EXT_DISP_IFACE_CTRL_2,	0x0002, 0 },97	{ POWER_CTRL_2,			0x0007, 0 },98	{ POWER_CTRL_3,			0x0000, 0 },99	{ POWER_CTRL_4,			0x0000, 200 },100	{ DISPLAY_CTRL_1,		0x0101, 0 },101	{ POWER_CTRL_1,			0x12B0, 0 },102	{ POWER_CTRL_2,			0x0007, 0 },103	{ POWER_CTRL_3,			0x01BB, 50 },104	{ POWER_CTRL_4,			0x0013, 0 },105	{ POWER_CTRL_7,			0x0010, 50 },106	{ GAMMA_CTRL_1,			0x000A, 0 },107	{ GAMMA_CTRL_2,			0x1326, 0 },108	{ GAMMA_CTRL_3,			0x0A29, 0 },109	{ GAMMA_CTRL_4,			0x0A0A, 0 },110	{ GAMMA_CTRL_5,			0x1E03, 0 },111	{ GAMMA_CTRL_6,			0x031E, 0 },112	{ GAMMA_CTRL_7,			0x0706, 0 },113	{ GAMMA_CTRL_8,			0x0303, 0 },114	{ GAMMA_CTRL_9,			0x010E, 0 },115	{ GAMMA_CTRL_10,		0x040E, 0 },116	{ WINDOW_HORIZ_RAM_START,	0x0000, 0 },117	{ WINDOW_HORIZ_RAM_END,		0x00EF, 0 },118	{ WINDOW_VERT_RAM_START,	0x0000, 0 },119	{ WINDOW_VERT_RAM_END,		0x013F, 0 },120	{ DRIVER_OUTPUT_CTRL_2,		0x2700, 0 },121	{ BASE_IMG_DISPLAY_CTRL,	0x0001, 0 },122	{ VERT_SCROLL_CTRL,		0x0000, 0 },123	{ PD1_DISPLAY_POS,		0x0000, 0 },124	{ PD1_RAM_START,		0x0000, 0 },125	{ PD1_RAM_END,			0x0000, 0 },126	{ PD2_DISPLAY_POS,		0x0000, 0 },127	{ PD2_RAM_START,		0x0000, 0 },128	{ PD2_RAM_END,			0x0000, 0 },129	{ PANEL_IFACE_CTRL_1,		0x0010, 0 },130	{ PANEL_IFACE_CTRL_2,		0x0000, 0 },131	{ PANEL_IFACE_CTRL_4,		0x0210, 0 },132	{ PANEL_IFACE_CTRL_5,		0x0000, 0 },133	{ DISPLAY_CTRL_1,		0x0133, 0 },134};135 136static struct otm3225a_spi_instruction display_enable_rgb_interface[] = {137	{ ENTRY_MODE,			0x1080, 0 },138	{ GRAM_ADDR_HORIZ_SET,		0x0000, 0 },139	{ GRAM_ADDR_VERT_SET,		0x0000, 0 },140	{ EXT_DISP_IFACE_CTRL_1,	0x0111, 500 },141};142 143static struct otm3225a_spi_instruction display_off[] = {144	{ DISPLAY_CTRL_1,	0x0131, 100 },145	{ DISPLAY_CTRL_1,	0x0130, 100 },146	{ DISPLAY_CTRL_1,	0x0100, 0 },147	{ POWER_CTRL_1,		0x0280, 0 },148	{ POWER_CTRL_3,		0x018B, 0 },149};150 151static struct otm3225a_spi_instruction display_on[] = {152	{ POWER_CTRL_1,		0x1280, 0 },153	{ DISPLAY_CTRL_1,	0x0101, 100 },154	{ DISPLAY_CTRL_1,	0x0121, 0 },155	{ DISPLAY_CTRL_1,	0x0123, 100 },156	{ DISPLAY_CTRL_1,	0x0133, 10 },157};158 159static void otm3225a_write(struct spi_device *spi,160			   struct otm3225a_spi_instruction *instruction,161			   unsigned int count)162{163	unsigned char buf[3];164 165	while (count--) {166		/* address register using index register */167		buf[0] = OTM3225A_INDEX_REG;168		buf[1] = 0x00;169		buf[2] = instruction->reg;170		spi_write(spi, buf, 3);171 172		/* write data to addressed register */173		buf[0] = OTM3225A_DATA_REG;174		buf[1] = (instruction->value >> 8) & 0xff;175		buf[2] = instruction->value & 0xff;176		spi_write(spi, buf, 3);177 178		/* execute delay if any */179		if (instruction->delay)180			msleep(instruction->delay);181		instruction++;182	}183}184 185static int otm3225a_set_power(struct lcd_device *ld, int power)186{187	struct otm3225a_data *dd = lcd_get_data(ld);188 189	if (power == dd->power)190		return 0;191 192	if (power > FB_BLANK_UNBLANK)193		otm3225a_write(dd->spi, display_off, ARRAY_SIZE(display_off));194	else195		otm3225a_write(dd->spi, display_on, ARRAY_SIZE(display_on));196	dd->power = power;197 198	return 0;199}200 201static int otm3225a_get_power(struct lcd_device *ld)202{203	struct otm3225a_data *dd = lcd_get_data(ld);204 205	return dd->power;206}207 208static const struct lcd_ops otm3225a_ops = {209	.set_power = otm3225a_set_power,210	.get_power = otm3225a_get_power,211};212 213static int otm3225a_probe(struct spi_device *spi)214{215	struct otm3225a_data *dd;216	struct lcd_device *ld;217	struct device *dev = &spi->dev;218 219	dd = devm_kzalloc(dev, sizeof(struct otm3225a_data), GFP_KERNEL);220	if (dd == NULL)221		return -ENOMEM;222 223	ld = devm_lcd_device_register(dev, dev_name(dev), dev, dd,224				      &otm3225a_ops);225	if (IS_ERR(ld))226		return PTR_ERR(ld);227 228	dd->spi = spi;229	dd->ld = ld;230	dev_set_drvdata(dev, dd);231 232	dev_info(dev, "Initializing and switching to RGB interface");233	otm3225a_write(spi, display_init, ARRAY_SIZE(display_init));234	otm3225a_write(spi, display_enable_rgb_interface,235		       ARRAY_SIZE(display_enable_rgb_interface));236	return 0;237}238 239static struct spi_driver otm3225a_driver = {240	.driver = {241		.name = "otm3225a",242	},243	.probe = otm3225a_probe,244};245 246module_spi_driver(otm3225a_driver);247 248MODULE_AUTHOR("Felix Brack <fb@ltec.ch>");249MODULE_DESCRIPTION("OTM3225A TFT LCD driver");250MODULE_VERSION("1.0.0");251MODULE_LICENSE("GPL v2");252