@@ -61,7 +61,7 @@
* 3. 8-bit with the Data/Command signal as a separate D/CX pin
*
* Currently mipi_dbi only supports Type C options 1 and 3 with
- * mipi_dbi_spi_init().
+ * mipi_dbi_spi_init() and Type B with mipi_dbi_gpio_init().
*/
#define MIPI_DBI_DEBUG_COMMAND(cmd, data, len) \
@@ -701,6 +701,15 @@ int mipi_dbi_poweron_conditional_reset(struct mipi_dbi_dev *dbidev)
}
EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset);
+static bool mipi_dbi_machine_little_endian(void)
+{
+#if defined(__LITTLE_ENDIAN)
+ return true;
+#else
+ return false;
+#endif
+}
+
#if IS_ENABLED(CONFIG_SPI)
/**
@@ -721,15 +730,6 @@ u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len)
}
EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed);
-static bool mipi_dbi_machine_little_endian(void)
-{
-#if defined(__LITTLE_ENDIAN)
- return true;
-#else
- return false;
-#endif
-}
-
/*
* MIPI DBI Type C Option 1
*
@@ -1158,6 +1158,120 @@ EXPORT_SYMBOL(mipi_dbi_spi_transfer);
#endif /* CONFIG_SPI */
+/*
+ * This function implements data transfer only from host to display.
+ */
+static void mipi_dbi_gpio_transfer(struct mipi_dbi *dbi, u16 data)
+{
+ unsigned long ldata = data;
+
+ /*
+ * Set W/R to low to start transfer.
+ * Set DB bits with provided data when W/R is low.
+ */
+ gpiod_set_value_cansleep(dbi->wr, 0);
+ gpiod_set_array_value_cansleep(dbi->db->ndescs, dbi->db->desc,
+ dbi->db->info, &ldata);
+
+ /*
+ * The bus usually needs additional delay.
+ */
+ ndelay(dbi->wr_up_delay);
+
+ /*
+ * Set W/R to high to indicate that DB lines are set.
+ */
+ gpiod_set_value_cansleep(dbi->wr, 1);
+
+ /*
+ * The connected display needs some time to read the data.
+ */
+ ndelay(dbi->wr_down_delay);
+}
+
+static int mipi_dbi_gpio_command(struct mipi_dbi *dbi, u8 *cmd,
+ u8 *par, size_t num)
+{
+ int i;
+
+ /*
+ * Read commands are not currently supported.
+ */
+ if (mipi_dbi_command_is_read(dbi, *cmd))
+ return -EOPNOTSUPP;
+
+ MIPI_DBI_DEBUG_COMMAND(*cmd, par, num);
+
+ gpiod_set_value_cansleep(dbi->dc, 0);
+ mipi_dbi_gpio_transfer(dbi, (u16)*cmd);
+ gpiod_set_value_cansleep(dbi->dc, 1);
+
+ if (dbi->db->ndescs == 16 &&
+ (*cmd == MIPI_DCS_WRITE_MEMORY_START ||
+ *cmd == MIPI_DCS_WRITE_MEMORY_CONTINUE)) {
+ /*
+ * Only a couple of commands supports 16-bit transfer.
+ */
+ for (i = 0; i < num; i += 2) {
+ u16 data = *(u16 *)&par[i];
+
+ if (dbi->swap_bytes)
+ data = (data >> 8) | (data << 8);
+
+ mipi_dbi_gpio_transfer(dbi, data);
+ }
+ } else {
+ for (i = 0; i < num; i++) {
+ /*
+ * Other commands ignore most significant bits.
+ */
+ mipi_dbi_gpio_transfer(dbi, (u16)par[i]);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * mipi_dbi_gpio_init - Initialize MIPI DBI Type B interface implemented via GPIO
+ * @dbi: MIPI DBI structure to initialize
+ * @dc: D/C gpio
+ * @wr: W/R gpio
+ * @db: DB gpios
+ * @wr_up_delay: Delay after setting DB and before changing W/R from low to high
+ * @wr_down_delay: Delay after changing W/R from low to high
+ *
+ * This function sets &mipi_dbi->command, enables &mipi_dbi->read_commands for the
+ * usual read commands. It should be followed by a call to mipi_dbi_dev_init() or
+ * a driver-specific init.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
+ */
+int mipi_dbi_gpio_init(struct mipi_dbi *dbi, struct gpio_desc *dc,
+ struct gpio_desc *wr, struct gpio_descs *db,
+ unsigned long wr_up_delay, unsigned long wr_down_delay)
+{
+ dbi->spi = NULL; /* Type B uses GPIO lines rather than SPI */
+
+ dbi->read_commands = mipi_dbi_dcs_read_commands;
+ dbi->command = mipi_dbi_gpio_command;
+
+ dbi->dc = dc;
+ dbi->wr = wr;
+ dbi->db = db;
+ dbi->wr_up_delay = wr_up_delay;
+ dbi->wr_down_delay = wr_down_delay;
+
+ if (mipi_dbi_machine_little_endian())
+ dbi->swap_bytes = true;
+
+ mutex_init(&dbi->cmdlock);
+
+ return 0;
+}
+EXPORT_SYMBOL(mipi_dbi_gpio_init);
+
#ifdef CONFIG_DEBUG_FS
static ssize_t mipi_dbi_debugfs_command_write(struct file *file,
@@ -55,7 +55,7 @@ struct mipi_dbi {
struct spi_device *spi;
/**
- * @dc: Optional D/C gpio.
+ * @dc: D/C gpio, optional for Type C and mandatory for Type B.
*/
struct gpio_desc *dc;
@@ -68,6 +68,31 @@ struct mipi_dbi {
* @tx_buf9_len: Size of tx_buf9.
*/
size_t tx_buf9_len;
+
+ /* Type B specific */
+
+ /**
+ * @wr: W/R gpio.
+ */
+ struct gpio_desc *wr;
+
+ /**
+ * @db: Data Bus gpios (usually 8 or 16).
+ */
+ struct gpio_descs *db;
+
+ /**
+ * @wr_up_delay: Delay after setting all db lines and before changing
+ * wr from low to high.
+ */
+ unsigned long wr_up_delay;
+
+ /**
+ * @wr_down_delay: Delay after changing wr from low to high and
+ * before wr can be changed again from hight to low to start a new
+ * write operation.
+ */
+ unsigned long wr_down_delay;
};
/**
@@ -139,6 +164,9 @@ static inline struct mipi_dbi_dev *drm_to_mipi_dbi_dev(struct drm_device *drm)
int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi,
struct gpio_desc *dc);
+int mipi_dbi_gpio_init(struct mipi_dbi *dbi, struct gpio_desc *dc,
+ struct gpio_desc *wr, struct gpio_descs *db,
+ unsigned long wr_up_delay, unsigned long wr_down_delay);
int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev,
const struct drm_simple_display_pipe_funcs *funcs,
const uint32_t *formats, unsigned int format_count,