// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright 2008 * Stefano Babic, DENX Software Engineering, sbabic@denx.de. * * This driver implements a lcd device for the ILITEK 922x display * controller. The interface to the display is SPI and the display's * memory is cyclically updated over the RGB interface.
*/
/* * maximum frequency for register access * (not for the GRAM access)
*/ #define ILITEK_MAX_FREQ_REG 4000000
/* * Device ID as found in the datasheet (supports 9221 and 9222)
*/ #define ILITEK_DEVICE_ID 0x9220 #define ILITEK_DEVICE_ID_MASK 0xFFF0
/* Last two bits in the START BYTE */ #define START_RS_INDEX 0 #define START_RS_REG 1 #define START_RW_WRITE 0 #define START_RW_READ 1
/* * START_BYTE(id, rs, rw) * * Set the start byte according to the required operation. * The start byte is defined as: * ---------------------------------- * | 0 | 1 | 1 | 1 | 0 | ID | RS | RW | * ---------------------------------- * @id: display's id as set by the manufacturer * @rs: operation type bit, one of: * - START_RS_INDEX set the index register * - START_RS_REG write/read registers/GRAM * @rw: read/write operation * - START_RW_WRITE write * - START_RW_READ read
*/ #define START_BYTE(id, rs, rw) \
(0x70 | (((id) & 0x01) << 2) | (((rs) & 0x01) << 1) | ((rw) & 0x01))
/* * CHECK_FREQ_REG(spi_device s, spi_transfer x) - Check the frequency * for the SPI transfer. According to the datasheet, the controller * accept higher frequency for the GRAM transfer, but it requires * lower frequency when the registers are read/written. * The macro sets the frequency in the spi_transfer structure if * the frequency exceeds the maximum value. * @s: pointer to an SPI device * @x: pointer to the read/write buffer pair
*/ #define CHECK_FREQ_REG(s, x) \ do { \ if (s->max_speed_hz > ILITEK_MAX_FREQ_REG) \
((struct spi_transfer *)x)->speed_hz = \
ILITEK_MAX_FREQ_REG; \
} while (0)
tbuf[0] = set_tx_byte(START_BYTE(ili922x_id, START_RS_INDEX,
START_RW_READ)); /* * we need 4-byte xfer here due to invalid dummy byte * received after start byte
*/ for (i = 1; i < 4; i++)
tbuf[i] = set_tx_byte(0); /* dummy */
/** * ili922x_write - write a controller register * @spi: struct spi_device * * @reg: offset of the register to be written * @value: value to be written
*/ staticint ili922x_write(struct spi_device *spi, u8 reg, u16 value)
{ struct spi_message msg; struct spi_transfer xfer_regindex, xfer_regvalue; unsignedchar tbuf[CMD_BUFSIZE]; unsignedchar rbuf[CMD_BUFSIZE]; int ret;
/** * ili922x_poweron - turn the display on * @spi: spi device * * The sequence to turn on the display is taken from * the datasheet and/or the example code provided by the * manufacturer.
*/ staticint ili922x_poweron(struct spi_device *spi)
{ int ret;
/* Power on */
ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000);
usleep_range(10000, 10500);
ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000);
msleep(40);
ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000);
msleep(40); /* register 0x56 is not documented in the datasheet */
ret += ili922x_write(spi, 0x56, 0x080F);
ret += ili922x_write(spi, REG_POWER_CONTROL_1, 0x4240);
usleep_range(10000, 10500);
ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0014);
msleep(40);
ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x1319);
msleep(40);
return ret;
}
/** * ili922x_poweroff - turn the display off * @spi: spi device
*/ staticint ili922x_poweroff(struct spi_device *spi)
{ int ret;
/* Power off */
ret = ili922x_write(spi, REG_POWER_CONTROL_1, 0x0000);
usleep_range(10000, 10500);
ret += ili922x_write(spi, REG_POWER_CONTROL_2, 0x0000);
ret += ili922x_write(spi, REG_POWER_CONTROL_3, 0x0000);
msleep(40);
ret += ili922x_write(spi, REG_POWER_CONTROL_4, 0x0000);
msleep(40);
staticint ili922x_lcd_power(struct ili922x *lcd, int power)
{ int ret = 0;
if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power))
ret = ili922x_poweron(lcd->spi); elseif (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power))
ret = ili922x_poweroff(lcd->spi);
ili = devm_kzalloc(&spi->dev, sizeof(*ili), GFP_KERNEL); if (!ili) return -ENOMEM;
ili->spi = spi;
spi_set_drvdata(spi, ili);
/* check if the device is connected */
ret = ili922x_read(spi, REG_DRIVER_CODE_READ, ®); if (ret || ((reg & ILITEK_DEVICE_ID_MASK) != ILITEK_DEVICE_ID)) {
dev_err(&spi->dev, "no LCD found: Chip ID 0x%x, ret %d\n",
reg, ret); return -ENODEV;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.