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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | /* SPDX-License-Identifier: GPL-2.0-or-later */ /* * MIPI Display Bus Interface (DBI) LCD controller support * * Copyright 2016 Noralf Trønnes */ #ifndef __LINUX_MIPI_DBI_H #define __LINUX_MIPI_DBI_H #include <linux/mutex.h> #include <drm/drm_device.h> #include <drm/drm_simple_kms_helper.h> struct drm_rect; struct gpio_desc; struct iosys_map; struct regulator; struct spi_device; /** * struct mipi_dbi - MIPI DBI interface */ struct mipi_dbi { /** * @cmdlock: Command lock */ struct mutex cmdlock; /** * @command: Bus specific callback executing commands. */ int (*command)(struct mipi_dbi *dbi, u8 *cmd, u8 *param, size_t num); /** * @read_commands: Array of read commands terminated by a zero entry. * Reading is disabled if this is NULL. */ const u8 *read_commands; /** * @swap_bytes: Swap bytes in buffer before transfer */ bool swap_bytes; /** * @reset: Optional reset gpio */ struct gpio_desc *reset; /* Type C specific */ /** * @spi: SPI device */ struct spi_device *spi; /** * @dc: Optional D/C gpio. */ struct gpio_desc *dc; /** * @tx_buf9: Buffer used for Option 1 9-bit conversion */ void *tx_buf9; /** * @tx_buf9_len: Size of tx_buf9. */ size_t tx_buf9_len; }; /** * struct mipi_dbi_dev - MIPI DBI device */ struct mipi_dbi_dev { /** * @drm: DRM device */ struct drm_device drm; /** * @pipe: Display pipe structure */ struct drm_simple_display_pipe pipe; /** * @connector: Connector */ struct drm_connector connector; /** * @mode: Fixed display mode */ struct drm_display_mode mode; /** * @tx_buf: Buffer used for transfer (copy clip rect area) */ u16 *tx_buf; /** * @rotation: initial rotation in degrees Counter Clock Wise */ unsigned int rotation; /** * @left_offset: Horizontal offset of the display relative to the * controller's driver array */ unsigned int left_offset; /** * @top_offset: Vertical offset of the display relative to the * controller's driver array */ unsigned int top_offset; /** * @backlight: backlight device (optional) */ struct backlight_device *backlight; /** * @regulator: power regulator (Vdd) (optional) */ struct regulator *regulator; /** * @io_regulator: I/O power regulator (Vddi) (optional) */ struct regulator *io_regulator; /** * @dbi: MIPI DBI interface */ struct mipi_dbi dbi; /** * @driver_private: Driver private data. * Necessary for drivers with private data since devm_drm_dev_alloc() * can't allocate structures that embed a structure which then again * embeds drm_device. */ void *driver_private; }; static inline struct mipi_dbi_dev *drm_to_mipi_dbi_dev(struct drm_device *drm) { return container_of(drm, struct mipi_dbi_dev, drm); } int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi, struct gpio_desc *dc); 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, const struct drm_display_mode *mode, unsigned int rotation, size_t tx_buf_size); int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, const struct drm_simple_display_pipe_funcs *funcs, const struct drm_display_mode *mode, unsigned int rotation); enum drm_mode_status mipi_dbi_pipe_mode_valid(struct drm_simple_display_pipe *pipe, const struct drm_display_mode *mode); void mipi_dbi_pipe_update(struct drm_simple_display_pipe *pipe, struct drm_plane_state *old_state); void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, struct drm_crtc_state *crtc_state, struct drm_plane_state *plan_state); void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe); int mipi_dbi_pipe_begin_fb_access(struct drm_simple_display_pipe *pipe, struct drm_plane_state *plane_state); void mipi_dbi_pipe_end_fb_access(struct drm_simple_display_pipe *pipe, struct drm_plane_state *plane_state); void mipi_dbi_pipe_reset_plane(struct drm_simple_display_pipe *pipe); struct drm_plane_state *mipi_dbi_pipe_duplicate_plane_state(struct drm_simple_display_pipe *pipe); void mipi_dbi_pipe_destroy_plane_state(struct drm_simple_display_pipe *pipe, struct drm_plane_state *plane_state); void mipi_dbi_hw_reset(struct mipi_dbi *dbi); bool mipi_dbi_display_is_on(struct mipi_dbi *dbi); int mipi_dbi_poweron_reset(struct mipi_dbi_dev *dbidev); int mipi_dbi_poweron_conditional_reset(struct mipi_dbi_dev *dbidev); u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len); int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz, u8 bpw, const void *buf, size_t len); int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val); int mipi_dbi_command_buf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len); int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, const u8 *data, size_t len); int mipi_dbi_buf_copy(void *dst, struct iosys_map *src, struct drm_framebuffer *fb, struct drm_rect *clip, bool swap); /** * mipi_dbi_command - MIPI DCS command with optional parameter(s) * @dbi: MIPI DBI structure * @cmd: Command * @seq: Optional parameter(s) * * Send MIPI DCS command to the controller. Use mipi_dbi_command_read() for * get/read. * * Returns: * Zero on success, negative error code on failure. */ #define mipi_dbi_command(dbi, cmd, seq...) \ ({ \ const u8 d[] = { seq }; \ struct device *dev = &(dbi)->spi->dev; \ int ret; \ ret = mipi_dbi_command_stackbuf(dbi, cmd, d, ARRAY_SIZE(d)); \ if (ret) \ dev_err_ratelimited(dev, "error %d when sending command %#02x\n", ret, cmd); \ ret; \ }) #ifdef CONFIG_DEBUG_FS void mipi_dbi_debugfs_init(struct drm_minor *minor); #else static inline void mipi_dbi_debugfs_init(struct drm_minor *minor) {} #endif /** * DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS - Initializes struct drm_simple_display_pipe_funcs * for MIPI-DBI devices * @enable_: Enable-callback implementation * * This macro initializes struct drm_simple_display_pipe_funcs with default * values for MIPI-DBI-based devices. The only callback that depends on the * hardware is @enable, for which the driver has to provide an implementation. * MIPI-based drivers are encouraged to use this macro for initialization. */ #define DRM_MIPI_DBI_SIMPLE_DISPLAY_PIPE_FUNCS(enable_) \ .mode_valid = mipi_dbi_pipe_mode_valid, \ .enable = (enable_), \ .disable = mipi_dbi_pipe_disable, \ .update = mipi_dbi_pipe_update, \ .begin_fb_access = mipi_dbi_pipe_begin_fb_access, \ .end_fb_access = mipi_dbi_pipe_end_fb_access, \ .reset_plane = mipi_dbi_pipe_reset_plane, \ .duplicate_plane_state = mipi_dbi_pipe_duplicate_plane_state, \ .destroy_plane_state = mipi_dbi_pipe_destroy_plane_state #endif /* __LINUX_MIPI_DBI_H */ |