#ifndef __DRM_MIPI_DSI_H__
#define __DRM_MIPI_DSI_H__
#include <linux/device.h>
struct mipi_dsi_host;
struct mipi_dsi_device;
struct drm_dsc_picture_parameter_set;
#define MIPI_DSI_MSG_REQ_ACK BIT(0)
#define MIPI_DSI_MSG_USE_LPM BIT(1)
struct mipi_dsi_msg {
u8 channel;
u8 type;
u16 flags;
size_t tx_len;
const void *tx_buf;
size_t rx_len;
void *rx_buf;
};
bool mipi_dsi_packet_format_is_short(u8 type);
bool mipi_dsi_packet_format_is_long(u8 type);
struct mipi_dsi_packet {
size_t size;
u8 header[4];
size_t payload_length;
const u8 *payload;
};
int mipi_dsi_create_packet(struct mipi_dsi_packet *packet,
const struct mipi_dsi_msg *msg);
struct mipi_dsi_host_ops {
int (*attach)(struct mipi_dsi_host *host,
struct mipi_dsi_device *dsi);
int (*detach)(struct mipi_dsi_host *host,
struct mipi_dsi_device *dsi);
ssize_t (*transfer)(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg);
};
struct mipi_dsi_host {
struct device *dev;
const struct mipi_dsi_host_ops *ops;
struct list_head list;
};
int mipi_dsi_host_register(struct mipi_dsi_host *host);
void mipi_dsi_host_unregister(struct mipi_dsi_host *host);
struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node);
#define MIPI_DSI_MODE_VIDEO BIT(0)
#define MIPI_DSI_MODE_VIDEO_BURST BIT(1)
#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2)
#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3)
#define MIPI_DSI_MODE_VIDEO_HSE BIT(4)
#define MIPI_DSI_MODE_VIDEO_NO_HFP BIT(5)
#define MIPI_DSI_MODE_VIDEO_NO_HBP BIT(6)
#define MIPI_DSI_MODE_VIDEO_NO_HSA BIT(7)
#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8)
#define MIPI_DSI_MODE_NO_EOT_PACKET BIT(9)
#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10)
#define MIPI_DSI_MODE_LPM BIT(11)
#define MIPI_DSI_HS_PKT_END_ALIGNED BIT(12)
enum mipi_dsi_pixel_format {
MIPI_DSI_FMT_RGB888,
MIPI_DSI_FMT_RGB666,
MIPI_DSI_FMT_RGB666_PACKED,
MIPI_DSI_FMT_RGB565,
};
#define DSI_DEV_NAME_SIZE 20
struct mipi_dsi_device_info {
char type[DSI_DEV_NAME_SIZE];
u32 channel;
struct device_node *node;
};
struct mipi_dsi_device {
struct mipi_dsi_host *host;
struct device dev;
char name[DSI_DEV_NAME_SIZE];
unsigned int channel;
unsigned int lanes;
enum mipi_dsi_pixel_format format;
unsigned long mode_flags;
unsigned long hs_rate;
unsigned long lp_rate;
struct drm_dsc_config *dsc;
};
#define MIPI_DSI_MODULE_PREFIX "mipi-dsi:"
#define to_mipi_dsi_device(__dev) container_of_const(__dev, struct mipi_dsi_device, dev)
static inline int mipi_dsi_pixel_format_to_bpp(enum mipi_dsi_pixel_format fmt)
{
switch (fmt) {
case MIPI_DSI_FMT_RGB888:
case MIPI_DSI_FMT_RGB666:
return 24;
case MIPI_DSI_FMT_RGB666_PACKED:
return 18;
case MIPI_DSI_FMT_RGB565:
return 16;
}
return -EINVAL;
}
struct mipi_dsi_device *
mipi_dsi_device_register_full(struct mipi_dsi_host *host,
const struct mipi_dsi_device_info *info);
void mipi_dsi_device_unregister(struct mipi_dsi_device *dsi);
struct mipi_dsi_device *
devm_mipi_dsi_device_register_full(struct device *dev, struct mipi_dsi_host *host,
const struct mipi_dsi_device_info *info);
struct mipi_dsi_device *of_find_mipi_dsi_device_by_node(struct device_node *np);
int mipi_dsi_attach(struct mipi_dsi_device *dsi);
int mipi_dsi_detach(struct mipi_dsi_device *dsi);
int devm_mipi_dsi_attach(struct device *dev, struct mipi_dsi_device *dsi);
int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi);
int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi);
int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi,
u16 value);
ssize_t mipi_dsi_compression_mode(struct mipi_dsi_device *dsi, bool enable);
ssize_t mipi_dsi_picture_parameter_set(struct mipi_dsi_device *dsi,
const struct drm_dsc_picture_parameter_set *pps);
ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload,
size_t size);
ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params,
size_t num_params, void *data, size_t size);
enum mipi_dsi_dcs_tear_mode {
MIPI_DSI_DCS_TEAR_MODE_VBLANK,
MIPI_DSI_DCS_TEAR_MODE_VHBLANK,
};
#define MIPI_DSI_DCS_POWER_MODE_DISPLAY (1 << 2)
#define MIPI_DSI_DCS_POWER_MODE_NORMAL (1 << 3)
#define MIPI_DSI_DCS_POWER_MODE_SLEEP (1 << 4)
#define MIPI_DSI_DCS_POWER_MODE_PARTIAL (1 << 5)
#define MIPI_DSI_DCS_POWER_MODE_IDLE (1 << 6)
ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi,
const void *data, size_t len);
ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd,
const void *data, size_t len);
ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
size_t len);
int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode);
int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format);
int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
u16 end);
int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
u16 end);
int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
enum mipi_dsi_dcs_tear_mode mode);
int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format);
int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline);
int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi,
u16 brightness);
int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi,
u16 *brightness);
int mipi_dsi_dcs_set_display_brightness_large(struct mipi_dsi_device *dsi,
u16 brightness);
int mipi_dsi_dcs_get_display_brightness_large(struct mipi_dsi_device *dsi,
u16 *brightness);
#define mipi_dsi_generic_write_seq(dsi, seq...) \
do { \
static const u8 d[] = { seq }; \
struct device *dev = &dsi->dev; \
int ret; \
ret = mipi_dsi_generic_write(dsi, d, ARRAY_SIZE(d)); \
if (ret < 0) { \
dev_err_ratelimited(dev, "transmit data failed: %d\n", \
ret); \
return ret; \
} \
} while (0)
#define mipi_dsi_dcs_write_seq(dsi, cmd, seq...) \
do { \
static const u8 d[] = { cmd, seq }; \
struct device *dev = &dsi->dev; \
int ret; \
ret = mipi_dsi_dcs_write_buffer(dsi, d, ARRAY_SIZE(d)); \
if (ret < 0) { \
dev_err_ratelimited( \
dev, "sending command %#02x failed: %d\n", \
cmd, ret); \
return ret; \
} \
} while (0)
struct mipi_dsi_driver {
struct device_driver driver;
int(*probe)(struct mipi_dsi_device *dsi);
void (*remove)(struct mipi_dsi_device *dsi);
void (*shutdown)(struct mipi_dsi_device *dsi);
};
static inline struct mipi_dsi_driver *
to_mipi_dsi_driver(struct device_driver *driver)
{
return container_of(driver, struct mipi_dsi_driver, driver);
}
static inline void *mipi_dsi_get_drvdata(const struct mipi_dsi_device *dsi)
{
return dev_get_drvdata(&dsi->dev);
}
static inline void mipi_dsi_set_drvdata(struct mipi_dsi_device *dsi, void *data)
{
dev_set_drvdata(&dsi->dev, data);
}
int mipi_dsi_driver_register_full(struct mipi_dsi_driver *driver,
struct module *owner);
void mipi_dsi_driver_unregister(struct mipi_dsi_driver *driver);
#define mipi_dsi_driver_register(driver) \
mipi_dsi_driver_register_full(driver, THIS_MODULE)
#define module_mipi_dsi_driver(__mipi_dsi_driver) \
module_driver(__mipi_dsi_driver, mipi_dsi_driver_register, \
mipi_dsi_driver_unregister)
#endif /* __DRM_MIPI_DSI__ */