From 1953e619473876f2a3732065877a2599a0b6e3b6 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Thu, 31 Jan 2019 10:07:23 +0800 Subject: [PATCH] video/drm: Sync MIPI DSI Bus helper from Linux 4.9 This imports drivers/gpu/drm/drm_mipi_dsi.c from Linux kernel 4.9. It can be very helpful when porting Linux mipi dsi driver to U-Boot. DSI hosts expose operations which can be used by DSI peripheral drivers to access associated devices. Change-Id: Iccfa9d946f33458867f4d4db0ce04aeb1918e855 Signed-off-by: Wyon Bi --- drivers/video/drm/Kconfig | 8 +- drivers/video/drm/Makefile | 2 +- drivers/video/drm/drm_mipi_dsi.c | 744 +++++++++++++++++++++ drivers/video/drm/dw_mipi_dsi.c | 135 ++-- drivers/video/drm/rockchip-inno-hdmi-phy.c | 3 +- drivers/video/drm/rockchip_connector.h | 5 - drivers/video/drm/rockchip_lvds.c | 3 +- drivers/video/drm/rockchip_mipi_dsi.c | 340 ---------- drivers/video/drm/rockchip_mipi_dsi.h | 202 ------ drivers/video/drm/rockchip_panel.c | 30 +- drivers/video/drm/rockchip_rgb.c | 2 + include/drm/drm_mipi_dsi.h | 252 +++++++ 12 files changed, 1120 insertions(+), 606 deletions(-) create mode 100644 drivers/video/drm/drm_mipi_dsi.c delete mode 100644 drivers/video/drm/rockchip_mipi_dsi.c delete mode 100644 drivers/video/drm/rockchip_mipi_dsi.h create mode 100644 include/drm/drm_mipi_dsi.h diff --git a/drivers/video/drm/Kconfig b/drivers/video/drm/Kconfig index 56a0ce3177..d2f5f0f998 100644 --- a/drivers/video/drm/Kconfig +++ b/drivers/video/drm/Kconfig @@ -13,7 +13,8 @@ menuconfig DRM_ROCKCHIP config DRM_ROCKCHIP_PANEL bool "Rockchip Panel Support" - select DRM_ROCKCHIP_MIPI_DSI + depends on DRM_ROCKCHIP + select DRM_MIPI_DSI config DRM_ROCKCHIP_DW_HDMI bool "Rockchip specific extensions for Synopsys DW HDMI" @@ -52,13 +53,14 @@ config DRM_ROCKCHIP_INNO_VIDEO_COMBO_PHY Enable this to support the Rockchip MIPI/LVDS/TTL PHY with Innosilicon IP block. -config DRM_ROCKCHIP_MIPI_DSI +config DRM_MIPI_DSI bool + depends on DRM_ROCKCHIP config DRM_ROCKCHIP_DW_MIPI_DSI tristate "Rockchip specific extensions for Synopsys DW MIPI DSI" depends on DRM_ROCKCHIP - select DRM_ROCKCHIP_MIPI_DSI + select DRM_MIPI_DSI select DRM_ROCKCHIP_PANEL help This selects support for Rockchip SoC specific extensions diff --git a/drivers/video/drm/Makefile b/drivers/video/drm/Makefile index 1cb4c53d03..46ae58c942 100644 --- a/drivers/video/drm/Makefile +++ b/drivers/video/drm/Makefile @@ -7,7 +7,7 @@ obj-y += rockchip_display.o rockchip_crtc.o rockchip_phy.o rockchip_bridge.o \ rockchip_vop.o rockchip_vop_reg.o bmp_helper.o -obj-$(CONFIG_DRM_ROCKCHIP_MIPI_DSI) += rockchip_mipi_dsi.o +obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o obj-$(CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI) += dw_mipi_dsi.o obj-$(CONFIG_DRM_ROCKCHIP_DW_HDMI) += rockchip_dw_hdmi.o dw_hdmi.o obj-$(CONFIG_ROCKCHIP_INNO_HDMI_PHY) += rockchip-inno-hdmi-phy.o diff --git a/drivers/video/drm/drm_mipi_dsi.c b/drivers/video/drm/drm_mipi_dsi.c new file mode 100644 index 0000000000..106f9f37c0 --- /dev/null +++ b/drivers/video/drm/drm_mipi_dsi.c @@ -0,0 +1,744 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. + * Andrzej Hajda + */ + +#include + +#include +#include +#include +#include + +/** + * mipi_dsi_attach - attach a DSI device to its DSI host + * @dsi: DSI peripheral + */ +int mipi_dsi_attach(struct mipi_dsi_device *dsi) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->attach) + return -ENOSYS; + + return ops->attach(dsi->host, dsi); +} + +/** + * mipi_dsi_detach - detach a DSI device from its DSI host + * @dsi: DSI peripheral + */ +int mipi_dsi_detach(struct mipi_dsi_device *dsi) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->detach) + return -ENOSYS; + + return ops->detach(dsi->host, dsi); +} + +static ssize_t mipi_dsi_device_transfer(struct mipi_dsi_device *dsi, + struct mipi_dsi_msg *msg) +{ + const struct mipi_dsi_host_ops *ops = dsi->host->ops; + + if (!ops || !ops->transfer) + return -ENOSYS; + + if (dsi->mode_flags & MIPI_DSI_MODE_LPM) + msg->flags |= MIPI_DSI_MSG_USE_LPM; + + return ops->transfer(dsi->host, msg); +} + +/** + * mipi_dsi_packet_format_is_short - check if a packet is of the short format + * @type: MIPI DSI data type of the packet + * + * Return: true if the packet for the given data type is a short packet, false + * otherwise. + */ +bool mipi_dsi_packet_format_is_short(u8 type) +{ + switch (type) { + case MIPI_DSI_V_SYNC_START: + case MIPI_DSI_V_SYNC_END: + case MIPI_DSI_H_SYNC_START: + case MIPI_DSI_H_SYNC_END: + case MIPI_DSI_END_OF_TRANSMISSION: + case MIPI_DSI_COLOR_MODE_OFF: + case MIPI_DSI_COLOR_MODE_ON: + case MIPI_DSI_SHUTDOWN_PERIPHERAL: + case MIPI_DSI_TURN_ON_PERIPHERAL: + case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: + case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: + case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: + case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: + case MIPI_DSI_DCS_SHORT_WRITE: + case MIPI_DSI_DCS_SHORT_WRITE_PARAM: + case MIPI_DSI_DCS_READ: + case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: + return true; + } + + return false; +} + +/** + * mipi_dsi_packet_format_is_long - check if a packet is of the long format + * @type: MIPI DSI data type of the packet + * + * Return: true if the packet for the given data type is a long packet, false + * otherwise. + */ +bool mipi_dsi_packet_format_is_long(u8 type) +{ + switch (type) { + case MIPI_DSI_NULL_PACKET: + case MIPI_DSI_BLANKING_PACKET: + case MIPI_DSI_GENERIC_LONG_WRITE: + case MIPI_DSI_DCS_LONG_WRITE: + case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16: + case MIPI_DSI_PACKED_PIXEL_STREAM_30: + case MIPI_DSI_PACKED_PIXEL_STREAM_36: + case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12: + case MIPI_DSI_PACKED_PIXEL_STREAM_16: + case MIPI_DSI_PACKED_PIXEL_STREAM_18: + case MIPI_DSI_PIXEL_STREAM_3BYTE_18: + case MIPI_DSI_PACKED_PIXEL_STREAM_24: + return true; + } + + return false; +} + +/** + * mipi_dsi_create_packet - create a packet from a message according to the + * DSI protocol + * @packet: pointer to a DSI packet structure + * @msg: message to translate into a packet + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, + const struct mipi_dsi_msg *msg) +{ + if (!packet || !msg) + return -EINVAL; + + /* do some minimum sanity checking */ + if (!mipi_dsi_packet_format_is_short(msg->type) && + !mipi_dsi_packet_format_is_long(msg->type)) + return -EINVAL; + + if (msg->channel > 3) + return -EINVAL; + + memset(packet, 0, sizeof(*packet)); + packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f); + if (mipi_dsi_packet_format_is_long(msg->type)) { + packet->header[1] = (msg->tx_len >> 0) & 0xff; + packet->header[2] = (msg->tx_len >> 8) & 0xff; + + packet->payload_length = msg->tx_len; + packet->payload = msg->tx_buf; + } else { + const u8 *tx = msg->tx_buf; + + packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0; + packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0; + } + + packet->size = sizeof(packet->header) + packet->payload_length; + + return 0; +} + +/** + * mipi_dsi_shutdown_peripheral() - sends a Shutdown Peripheral command + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_shutdown_peripheral(struct mipi_dsi_device *dsi) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_SHUTDOWN_PERIPHERAL, + .tx_buf = (u8 [2]) { 0, 0 }, + .tx_len = 2, + }; + int ret = mipi_dsi_device_transfer(dsi, &msg); + + return (ret < 0) ? ret : 0; +} + +/** + * mipi_dsi_turn_on_peripheral() - sends a Turn On Peripheral command + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_TURN_ON_PERIPHERAL, + .tx_buf = (u8 [2]) { 0, 0 }, + .tx_len = 2, + }; + int ret = mipi_dsi_device_transfer(dsi, &msg); + + return (ret < 0) ? ret : 0; +} + +/* + * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the + * the payload in a long packet transmitted from the peripheral back to the + * host processor + * @dsi: DSI peripheral device + * @value: the maximum size of the payload + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_set_maximum_return_packet_size(struct mipi_dsi_device *dsi, + u16 value) +{ + u8 tx[2] = { value & 0xff, value >> 8 }; + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, + .tx_len = sizeof(tx), + .tx_buf = tx, + }; + int ret = mipi_dsi_device_transfer(dsi, &msg); + + return (ret < 0) ? ret : 0; +} + +/** + * mipi_dsi_generic_write() - transmit data using a generic write packet + * @dsi: DSI peripheral device + * @payload: buffer containing the payload + * @size: size of payload buffer + * + * This function will automatically choose the right data type depending on + * the payload length. + * + * Return: The number of bytes transmitted on success or a negative error code + * on failure. + */ +ssize_t mipi_dsi_generic_write(struct mipi_dsi_device *dsi, const void *payload, + size_t size) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_buf = payload, + .tx_len = size + }; + + switch (size) { + case 0: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM; + break; + case 1: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM; + break; + case 2: + msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM; + break; + default: + msg.type = MIPI_DSI_GENERIC_LONG_WRITE; + break; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} + +/** + * mipi_dsi_generic_read() - receive data using a generic read packet + * @dsi: DSI peripheral device + * @params: buffer containing the request parameters + * @num_params: number of request parameters + * @data: buffer in which to return the received data + * @size: size of receive buffer + * + * This function will automatically choose the right data type depending on + * the number of parameters passed in. + * + * Return: The number of bytes successfully read or a negative error code on + * failure. + */ +ssize_t mipi_dsi_generic_read(struct mipi_dsi_device *dsi, const void *params, + size_t num_params, void *data, size_t size) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_len = num_params, + .tx_buf = params, + .rx_len = size, + .rx_buf = data + }; + + switch (num_params) { + case 0: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; + break; + + case 1: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; + break; + + case 2: + msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; + break; + + default: + return -EINVAL; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} + +/** + * mipi_dsi_dcs_write_buffer() - transmit a DCS command with payload + * @dsi: DSI peripheral device + * @data: buffer containing data to be transmitted + * @len: size of transmission buffer + * + * This function will automatically choose the right data type depending on + * the command payload length. + * + * Return: The number of bytes successfully transmitted or a negative error + * code on failure. + */ +ssize_t mipi_dsi_dcs_write_buffer(struct mipi_dsi_device *dsi, + const void *data, size_t len) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .tx_buf = data, + .tx_len = len + }; + + switch (len) { + case 0: + return -EINVAL; + + case 1: + msg.type = MIPI_DSI_DCS_SHORT_WRITE; + break; + + case 2: + msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM; + break; + + default: + msg.type = MIPI_DSI_DCS_LONG_WRITE; + break; + } + + return mipi_dsi_device_transfer(dsi, &msg); +} + +/** + * mipi_dsi_dcs_write() - send DCS write command + * @dsi: DSI peripheral device + * @cmd: DCS command + * @data: buffer containing the command payload + * @len: command payload length + * + * This function will automatically choose the right data type depending on + * the command payload length. + * + * Return: The number of bytes successfully transmitted or a negative error + * code on failure. + */ +ssize_t mipi_dsi_dcs_write(struct mipi_dsi_device *dsi, u8 cmd, + const void *data, size_t len) +{ + ssize_t err; + size_t size; + u8 *tx; + + if (len > 0) { + size = 1 + len; + + tx = malloc(size); + if (!tx) + return -ENOMEM; + + /* concatenate the DCS command byte and the payload */ + tx[0] = cmd; + memcpy(&tx[1], data, len); + } else { + tx = &cmd; + size = 1; + } + + err = mipi_dsi_dcs_write_buffer(dsi, tx, size); + + if (len > 0) + free(tx); + + return err; +} + +/** + * mipi_dsi_dcs_read() - send DCS read request command + * @dsi: DSI peripheral device + * @cmd: DCS command + * @data: buffer in which to receive data + * @len: size of receive buffer + * Return: The number of bytes read or a negative error code on failure. + */ +ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data, + size_t len) +{ + struct mipi_dsi_msg msg = { + .channel = dsi->channel, + .type = MIPI_DSI_DCS_READ, + .tx_buf = &cmd, + .tx_len = 1, + .rx_buf = data, + .rx_len = len + }; + + return mipi_dsi_device_transfer(dsi, &msg); +} + +/** + * mipi_dsi_dcs_nop() - send DCS nop packet + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_nop(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_NOP, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_soft_reset() - perform a software reset of the display module + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_soft_reset(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SOFT_RESET, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_get_power_mode() - query the display module's current power + * mode + * @dsi: DSI peripheral device + * @mode: return location for the current power mode + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_power_mode(struct mipi_dsi_device *dsi, u8 *mode) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_POWER_MODE, mode, + sizeof(*mode)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} + +/** + * mipi_dsi_dcs_get_pixel_format() - gets the pixel format for the RGB image + * data used by the interface + * @dsi: DSI peripheral device + * @format: return location for the pixel format + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_pixel_format(struct mipi_dsi_device *dsi, u8 *format) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_PIXEL_FORMAT, format, + sizeof(*format)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} + +/** + * mipi_dsi_dcs_enter_sleep_mode() - disable all unnecessary blocks inside the + * display module except interface communication + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_enter_sleep_mode(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_ENTER_SLEEP_MODE, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_exit_sleep_mode() - enable all blocks inside the display + * module + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_exit_sleep_mode(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_EXIT_SLEEP_MODE, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_display_off() - stop displaying the image data on the + * display device + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_display_off(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_OFF, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_display_on() - start displaying the image data on the + * display device + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_display_on(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_ON, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_column_address() - define the column extent of the frame + * memory accessed by the host processor + * @dsi: DSI peripheral device + * @start: first column of frame memory + * @end: last column of frame memory + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, + u16 end) +{ + u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_COLUMN_ADDRESS, payload, + sizeof(payload)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_page_address() - define the page extent of the frame + * memory accessed by the host processor + * @dsi: DSI peripheral device + * @start: first page of frame memory + * @end: last page of frame memory + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, + u16 end) +{ + u8 payload[4] = { start >> 8, start & 0xff, end >> 8, end & 0xff }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PAGE_ADDRESS, payload, + sizeof(payload)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_tear_off() - turn off the display module's Tearing Effect + * output signal on the TE signal line + * @dsi: DSI peripheral device + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_OFF, NULL, 0); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_tear_on() - turn on the display module's Tearing Effect + * output signal on the TE signal line. + * @dsi: DSI peripheral device + * @mode: the Tearing Effect Output Line mode + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, + enum mipi_dsi_dcs_tear_mode mode) +{ + u8 value = mode; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_ON, &value, + sizeof(value)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image + * data used by the interface + * @dsi: DSI peripheral device + * @format: pixel format + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_pixel_format(struct mipi_dsi_device *dsi, u8 format) +{ + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_PIXEL_FORMAT, &format, + sizeof(format)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for + * the Tearing Effect output signal of the display module + * @dsi: DSI peripheral device + * @scanline: scanline to use as trigger + * + * Return: 0 on success or a negative error code on failure + */ +int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline) +{ + u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8, + scanline & 0xff }; + ssize_t err; + + err = mipi_dsi_generic_write(dsi, payload, sizeof(payload)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_set_display_brightness() - sets the brightness value of the + * display + * @dsi: DSI peripheral device + * @brightness: brightness value + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_set_display_brightness(struct mipi_dsi_device *dsi, + u16 brightness) +{ + u8 payload[2] = { brightness & 0xff, brightness >> 8 }; + ssize_t err; + + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_DISPLAY_BRIGHTNESS, + payload, sizeof(payload)); + if (err < 0) + return err; + + return 0; +} + +/** + * mipi_dsi_dcs_get_display_brightness() - gets the current brightness value + * of the display + * @dsi: DSI peripheral device + * @brightness: brightness value + * + * Return: 0 on success or a negative error code on failure. + */ +int mipi_dsi_dcs_get_display_brightness(struct mipi_dsi_device *dsi, + u16 *brightness) +{ + ssize_t err; + + err = mipi_dsi_dcs_read(dsi, MIPI_DCS_GET_DISPLAY_BRIGHTNESS, + brightness, sizeof(*brightness)); + if (err <= 0) { + if (err == 0) + err = -ENODATA; + + return err; + } + + return 0; +} diff --git a/drivers/video/drm/dw_mipi_dsi.c b/drivers/video/drm/dw_mipi_dsi.c index ed831ed371..263bb7ac44 100644 --- a/drivers/video/drm/dw_mipi_dsi.c +++ b/drivers/video/drm/dw_mipi_dsi.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include + #include #include #include @@ -15,13 +17,15 @@ #include #include #include +#include #include "rockchip_display.h" #include "rockchip_crtc.h" #include "rockchip_connector.h" #include "rockchip_panel.h" #include "rockchip_phy.h" -#include "rockchip_mipi_dsi.h" + +#define UPDATE(v, h, l) (((v) << (l)) & GENMASK((h), (l))) #define DSI_VERSION 0x00 #define DSI_PWR_UP 0x04 @@ -300,7 +304,7 @@ static int genif_wait_w_pld_fifo_not_full(struct dw_mipi_dsi *dsi) int ret; ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, - sts, !(sts & GEN_PLD_W_FULL), 10, + sts, !(sts & GEN_PLD_W_FULL), CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { printf("generic write payload fifo is full\n"); @@ -316,7 +320,7 @@ static int genif_wait_cmd_fifo_not_full(struct dw_mipi_dsi *dsi) int ret; ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, - sts, !(sts & GEN_CMD_FULL), 10, + sts, !(sts & GEN_CMD_FULL), CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { printf("generic write cmd fifo is full\n"); @@ -334,7 +338,7 @@ static int genif_wait_write_fifo_empty(struct dw_mipi_dsi *dsi) mask = GEN_CMD_EMPTY | GEN_PLD_W_EMPTY; ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, - sts, (sts & mask) == mask, 10, + sts, (sts & mask) == mask, CMD_PKT_STATUS_TIMEOUT_US); if (ret < 0) { printf("generic write fifo is full\n"); @@ -469,8 +473,7 @@ static int mipi_dphy_power_on(struct dw_mipi_dsi *dsi) } ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, - val, val & PHY_LOCK, - 1000, PHY_STATUS_TIMEOUT_US); + val, val & PHY_LOCK, PHY_STATUS_TIMEOUT_US); if (ret < 0) { dev_err(dsi->dev, "PHY is not locked\n"); return ret; @@ -481,7 +484,7 @@ static int mipi_dphy_power_on(struct dw_mipi_dsi *dsi) mask = PHY_STOPSTATELANE; ret = readl_poll_timeout(dsi->base + DSI_PHY_STATUS, val, (val & mask) == mask, - 1000, PHY_STATUS_TIMEOUT_US); + PHY_STATUS_TIMEOUT_US); if (ret < 0) { dev_err(dsi->dev, "lane module is not in stop state\n"); return ret; @@ -525,7 +528,7 @@ static void dw_mipi_dsi_phy_init(struct dw_mipi_dsi *dsi) testif_write(dsi, 0x44, HSFREQRANGE(hsfreqrange)); txbyteclkhs = dsi->lane_mbps >> 3; - counter = txbyteclkhs * 60 / NSEC_PER_USEC; + counter = txbyteclkhs * 60 / 1000; testif_write(dsi, 0x60, 0x80 | counter); testif_write(dsi, 0x70, 0x80 | counter); @@ -549,7 +552,7 @@ static unsigned long dw_mipi_dsi_get_lane_rate(struct dw_mipi_dsi *dsi) /* optional override of the desired bandwidth */ value = dev_read_u32_default(dsi->dev, "rockchip,lane-rate", 0); if (value > 0) - return value * USEC_PER_SEC; + return value * 1000 * 1000; bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); if (bpp < 0) @@ -629,7 +632,7 @@ static void dw_mipi_dsi_set_pll(struct dw_mipi_dsi *dsi, unsigned long rate) } } - dsi->lane_mbps = best_freq / USEC_PER_SEC; + dsi->lane_mbps = best_freq / 1000 / 1000; dsi->dphy.input_div = best_prediv; dsi->dphy.feedback_div = best_fbdiv; if (dsi->slave) { @@ -648,7 +651,7 @@ static int dw_mipi_dsi_read_from_fifo(struct dw_mipi_dsi *dsi, int ret; ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, - val, !(val & GEN_RD_CMD_BUSY), 50, 5000); + val, !(val & GEN_RD_CMD_BUSY), 5000); if (ret) { printf("entire response isn't stored in the FIFO\n"); return ret; @@ -657,8 +660,7 @@ static int dw_mipi_dsi_read_from_fifo(struct dw_mipi_dsi *dsi, /* Receive payload */ for (length = msg->rx_len; length; length -= 4) { ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS, - val, !(val & GEN_PLD_R_EMPTY), - 50, 5000); + val, !(val & GEN_PLD_R_EMPTY), 5000); if (ret) { printf("Read payload FIFO is empty\n"); return ret; @@ -713,7 +715,7 @@ static ssize_t dw_mipi_dsi_transfer(struct dw_mipi_dsi *dsi, int ret; int val; - if (dsi->mode_flags & MIPI_DSI_MODE_LPM) { + if (msg->flags & MIPI_DSI_MSG_USE_LPM) { dsi_update_bits(dsi, DSI_VID_MODE_CFG, LP_CMD_EN, LP_CMD_EN); dsi_update_bits(dsi, DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS, 0); } else { @@ -858,15 +860,6 @@ static ssize_t dw_mipi_dsi_transfer(struct dw_mipi_dsi *dsi, return msg->rx_len ? msg->rx_len : msg->tx_len; } -static ssize_t dw_mipi_dsi_connector_transfer(struct display_state *state, - const struct mipi_dsi_msg *msg) -{ - struct connector_state *conn_state = &state->conn_state; - struct dw_mipi_dsi *dsi = dev_get_priv(conn_state->dev); - - return dw_mipi_dsi_transfer(dsi, msg); -} - static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) { u32 val = LP_VACT_EN | LP_VFP_EN | LP_VBP_EN | LP_VSA_EN | @@ -1017,7 +1010,7 @@ static int dw_mipi_dsi_get_hcomponent_lbcc(struct dw_mipi_dsi *dsi, { u32 lbcc; - lbcc = hcomponent * dsi->lane_mbps * MSEC_PER_SEC / 8; + lbcc = hcomponent * dsi->lane_mbps * 1000 / 8; if (dsi->mode->clock == 0) { printf("dsi mode clock is 0!\n"); @@ -1089,20 +1082,9 @@ static int dw_mipi_dsi_connector_init(struct display_state *state) { struct connector_state *conn_state = &state->conn_state; struct dw_mipi_dsi *dsi = dev_get_priv(conn_state->dev); - struct rockchip_panel *panel = state_get_panel(state); dsi->dphy.phy = conn_state->phy; - dsi->lanes = dev_read_u32_default(panel->dev, "dsi,lanes", 4); - dsi->format = dev_read_u32_default(panel->dev, "dsi,format", - MIPI_DSI_FMT_RGB888); - dsi->mode_flags = dev_read_u32_default(panel->dev, "dsi,flags", - MIPI_DSI_MODE_VIDEO | - MIPI_DSI_MODE_VIDEO_BURST | - MIPI_DSI_MODE_LPM | - MIPI_DSI_MODE_EOT_PACKET); - dsi->channel = dev_read_u32_default(panel->dev, "reg", 0); - conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; conn_state->color_space = V4L2_COLORSPACE_DEFAULT; conn_state->type = DRM_MODE_CONNECTOR_DSI; @@ -1122,7 +1104,7 @@ static int dw_mipi_dsi_connector_init(struct display_state *state) static void dw_mipi_dsi_set_hs_clk(struct dw_mipi_dsi *dsi, unsigned long rate) { rate = rockchip_phy_set_pll(dsi->dphy.phy, rate); - dsi->lane_mbps = rate / USEC_PER_SEC; + dsi->lane_mbps = rate / 1000 / 1000; } static void dw_mipi_dsi_host_init(struct dw_mipi_dsi *dsi) @@ -1256,7 +1238,6 @@ static const struct rockchip_connector_funcs dw_mipi_dsi_connector_funcs = { .unprepare = dw_mipi_dsi_connector_unprepare, .enable = dw_mipi_dsi_connector_enable, .disable = dw_mipi_dsi_connector_disable, - .transfer = dw_mipi_dsi_connector_transfer, }; static int dw_mipi_dsi_dual_channel_probe(struct dw_mipi_dsi *master) @@ -1515,11 +1496,89 @@ static const struct udevice_id dw_mipi_dsi_ids[] = { {} }; +static ssize_t dw_mipi_dsi_host_transfer(struct mipi_dsi_host *host, + const struct mipi_dsi_msg *msg) +{ + struct dw_mipi_dsi *dsi = dev_get_priv(host->dev); + + return dw_mipi_dsi_transfer(dsi, msg); +} + +static int dw_mipi_dsi_host_attach(struct mipi_dsi_host *host, + struct mipi_dsi_device *device) +{ + struct dw_mipi_dsi *dsi = dev_get_priv(host->dev); + + if (device->lanes < 1 || device->lanes > 8) + return -EINVAL; + + dsi->lanes = device->lanes; + dsi->channel = device->channel; + dsi->format = device->format; + dsi->mode_flags = device->mode_flags; + + return 0; +} + +static const struct mipi_dsi_host_ops dw_mipi_dsi_host_ops = { + .attach = dw_mipi_dsi_host_attach, + .transfer = dw_mipi_dsi_host_transfer, +}; + +static int dw_mipi_dsi_bind(struct udevice *dev) +{ + struct mipi_dsi_host *host = dev_get_platdata(dev); + + host->dev = dev; + host->ops = &dw_mipi_dsi_host_ops; + + return dm_scan_fdt_dev(dev); +} + +static int dw_mipi_dsi_child_post_bind(struct udevice *dev) +{ + struct mipi_dsi_host *host = dev_get_platdata(dev->parent); + struct mipi_dsi_device *device = dev_get_parent_platdata(dev); + + device->dev = dev; + device->host = host; + device->lanes = dev_read_u32_default(dev, "dsi,lanes", 4); + device->format = dev_read_u32_default(dev, "dsi,format", + MIPI_DSI_FMT_RGB888); + device->mode_flags = dev_read_u32_default(dev, "dsi,flags", + MIPI_DSI_MODE_VIDEO | + MIPI_DSI_MODE_VIDEO_BURST | + MIPI_DSI_MODE_VIDEO_HBP | + MIPI_DSI_MODE_LPM | + MIPI_DSI_MODE_EOT_PACKET); + device->channel = dev_read_u32_default(dev, "reg", 0); + + return 0; +} + +static int dw_mipi_dsi_child_pre_probe(struct udevice *dev) +{ + struct mipi_dsi_device *device = dev_get_parent_platdata(dev); + int ret; + + ret = mipi_dsi_attach(device); + if (ret) { + dev_err(dev, "mipi_dsi_attach() failed: %d\n", ret); + return ret; + } + + return 0; +} + U_BOOT_DRIVER(dw_mipi_dsi) = { .name = "dw_mipi_dsi", .id = UCLASS_DISPLAY, .of_match = dw_mipi_dsi_ids, .probe = dw_mipi_dsi_probe, - .bind = dm_scan_fdt_dev, + .bind = dw_mipi_dsi_bind, .priv_auto_alloc_size = sizeof(struct dw_mipi_dsi), + .per_child_platdata_auto_alloc_size = sizeof(struct mipi_dsi_device), + .platdata_auto_alloc_size = sizeof(struct mipi_dsi_host), + .child_post_bind = dw_mipi_dsi_child_post_bind, + .child_pre_probe = dw_mipi_dsi_child_pre_probe, }; diff --git a/drivers/video/drm/rockchip-inno-hdmi-phy.c b/drivers/video/drm/rockchip-inno-hdmi-phy.c index 783280083d..71c710fc86 100644 --- a/drivers/video/drm/rockchip-inno-hdmi-phy.c +++ b/drivers/video/drm/rockchip-inno-hdmi-phy.c @@ -20,11 +20,10 @@ #include "rockchip_display.h" #include "rockchip_crtc.h" -#include "rockchip_connector.h" #include "rockchip_phy.h" #define INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT 1000 -/*#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l)))*/ +#define UPDATE(x, h, l) (((x) << (l)) & GENMASK((h), (l))) /* REG: 0x00 */ #define PRE_PLL_REFCLK_SEL_MASK BIT(0) diff --git a/drivers/video/drm/rockchip_connector.h b/drivers/video/drm/rockchip_connector.h index 1ed54647c5..642238b1a7 100644 --- a/drivers/video/drm/rockchip_connector.h +++ b/drivers/video/drm/rockchip_connector.h @@ -7,8 +7,6 @@ #ifndef _ROCKCHIP_CONNECTOR_H_ #define _ROCKCHIP_CONNECTOR_H_ -#include "rockchip_mipi_dsi.h" - struct rockchip_connector { const struct rockchip_connector_funcs *funcs; @@ -58,9 +56,6 @@ struct rockchip_connector_funcs { * Save data to dts, then you can share data to kernel space. */ int (*fixup_dts)(struct display_state *state, void *blob); - /* transmit a DSI packet */ - ssize_t (*transfer)(struct display_state *state, - const struct mipi_dsi_msg *msg); }; const struct rockchip_connector * diff --git a/drivers/video/drm/rockchip_lvds.c b/drivers/video/drm/rockchip_lvds.c index b36c30d2f0..4e81a3549d 100644 --- a/drivers/video/drm/rockchip_lvds.c +++ b/drivers/video/drm/rockchip_lvds.c @@ -20,7 +20,8 @@ #include "rockchip_connector.h" #include "rockchip_phy.h" #include "rockchip_panel.h" -#include "rockchip_lvds.h" + +#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK(h, l) << 16)) #define PX30_GRF_PD_VO_CON1 0x0438 #define PX30_LVDS_SELECT(x) HIWORD_UPDATE(x, 14, 13) diff --git a/drivers/video/drm/rockchip_mipi_dsi.c b/drivers/video/drm/rockchip_mipi_dsi.c deleted file mode 100644 index 649f74281a..0000000000 --- a/drivers/video/drm/rockchip_mipi_dsi.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include -#include -#include -#include -#include - -#include "rockchip_display.h" -#include "rockchip_crtc.h" -#include "rockchip_connector.h" -#include "rockchip_mipi_dsi.h" - -void mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing, - unsigned long period) -{ - /* Global Operation Timing Parameters */ - timing->clkmiss = 0; - timing->clkpost = 70 + 52 * period; - timing->clkpre = 8 * period; - timing->clkprepare = 65; - timing->clksettle = 95; - timing->clktermen = 0; - timing->clktrail = 80; - timing->clkzero = 260; - timing->dtermen = 0; - timing->eot = 0; - timing->hsexit = 120; - timing->hsprepare = 65 + 4 * period; - timing->hszero = 145 + 6 * period; - timing->hssettle = 85 + 6 * period; - timing->hsskip = 40; - timing->hstrail = max(8 * period, 60 + 4 * period); - timing->init = 100000; - timing->lpx = 60; - timing->taget = 5 * timing->lpx; - timing->tago = 4 * timing->lpx; - timing->tasure = 2 * timing->lpx; - timing->wakeup = 1000000; -} - -ssize_t mipi_dsi_generic_write(struct display_state *state, - const void *payload, size_t size) -{ - struct connector_state *conn_state = &state->conn_state; - const struct rockchip_connector *connector = conn_state->connector; - struct mipi_dsi_msg msg; - - if (!connector || !connector->funcs || !connector->funcs->transfer) { - printf("%s: failed to find connector transfer funcs\n", __func__); - return -ENODEV; - } - - memset(&msg, 0, sizeof(msg)); - msg.channel = 0; - msg.tx_buf = payload; - msg.tx_len = size; - msg.flags |= MIPI_DSI_MSG_USE_LPM; - - switch (size) { - case 0: - msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM; - break; - case 1: - msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM; - break; - case 2: - msg.type = MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM; - break; - default: - msg.type = MIPI_DSI_GENERIC_LONG_WRITE; - break; - } - - return connector->funcs->transfer(state, &msg); -} - -ssize_t mipi_dsi_dcs_write(struct display_state *state, - const void *payload, size_t size) -{ - struct connector_state *conn_state = &state->conn_state; - const struct rockchip_connector *connector = conn_state->connector; - struct mipi_dsi_msg msg; - - if (!connector || !connector->funcs || !connector->funcs->transfer) { - printf("%s: failed to find connector transfer funcs\n", __func__); - return -ENODEV; - } - - memset(&msg, 0, sizeof(msg)); - msg.channel = 0; - msg.tx_buf = payload; - msg.tx_len = size; - msg.flags |= MIPI_DSI_MSG_USE_LPM; - - switch (size) { - case 0: - return -EINVAL; - case 1: - msg.type = MIPI_DSI_DCS_SHORT_WRITE; - break; - case 2: - msg.type = MIPI_DSI_DCS_SHORT_WRITE_PARAM; - break; - default: - msg.type = MIPI_DSI_DCS_LONG_WRITE; - break; - } - - return connector->funcs->transfer(state, &msg); -} - -ssize_t mipi_dsi_generic_read(struct display_state *state, const void *params, - size_t num_params, void *data, size_t size) -{ - struct connector_state *conn_state = &state->conn_state; - const struct rockchip_connector *connector = conn_state->connector; - struct mipi_dsi_msg msg; - - if (!connector || !connector->funcs || !connector->funcs->transfer) { - printf("%s: failed to find connector transfer funcs\n", __func__); - return -ENODEV; - } - - memset(&msg, 0, sizeof(msg)); - msg.channel = 0; - msg.tx_buf = params; - msg.tx_len = num_params; - msg.rx_len = size; - msg.rx_buf = data; - msg.flags |= MIPI_DSI_MSG_USE_LPM; - - switch (num_params) { - case 0: - msg.type = MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM; - break; - case 1: - msg.type = MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM; - break; - case 2: - msg.type = MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM; - break; - default: - return -EINVAL; - } - - return connector->funcs->transfer(state, &msg); -} - -ssize_t mipi_dsi_dcs_read(struct display_state *state, u8 cmd, void *data, - size_t len) -{ - struct connector_state *conn_state = &state->conn_state; - const struct rockchip_connector *connector = conn_state->connector; - struct mipi_dsi_msg msg; - - if (!connector || !connector->funcs || !connector->funcs->transfer) { - printf("%s: failed to find connector transfer funcs\n", __func__); - return -ENODEV; - } - - memset(&msg, 0, sizeof(msg)); - msg.channel = 0; - msg.type = MIPI_DSI_DCS_READ; - msg.tx_buf = &cmd; - msg.tx_len = 1; - msg.rx_len = len; - msg.rx_buf = data; - msg.flags |= MIPI_DSI_MSG_USE_LPM; - - return connector->funcs->transfer(state, &msg); -} - -ssize_t mipi_dsi_shutdown_peripheral(struct display_state *state) -{ - struct connector_state *conn_state = &state->conn_state; - const struct rockchip_connector *connector = conn_state->connector; - struct mipi_dsi_msg msg = { - .channel = 0, - .type = MIPI_DSI_SHUTDOWN_PERIPHERAL, - .tx_buf = (u8 [2]) { 0, 0 }, - .tx_len = 2, - .flags = MIPI_DSI_MSG_USE_LPM, - }; - - if (!connector) - return -ENODEV; - - if (!connector->funcs || !connector->funcs->transfer) - return -ENOSYS; - - return connector->funcs->transfer(state, &msg); -} - -ssize_t mipi_dsi_turn_on_peripheral(struct display_state *state) -{ - struct connector_state *conn_state = &state->conn_state; - const struct rockchip_connector *connector = conn_state->connector; - struct mipi_dsi_msg msg = { - .channel = 0, - .type = MIPI_DSI_TURN_ON_PERIPHERAL, - .tx_buf = (u8 [2]) { 0, 0 }, - .tx_len = 2, - .flags = MIPI_DSI_MSG_USE_LPM, - }; - - if (!connector) - return -ENODEV; - - if (!connector->funcs || !connector->funcs->transfer) - return -ENOSYS; - - return connector->funcs->transfer(state, &msg); -} - -int mipi_dsi_dcs_get_power_mode(struct display_state *state, u8 *mode) -{ - ssize_t err; - - err = mipi_dsi_dcs_read(state, MIPI_DCS_GET_POWER_MODE, mode, - sizeof(*mode)); - if (err <= 0) { - if (err == 0) - err = -ENODATA; - - return err; - } - - return 0; -} - -int mipi_dsi_set_maximum_return_packet_size(struct display_state *state, - u16 value) -{ - struct connector_state *conn_state = &state->conn_state; - const struct rockchip_connector *connector = conn_state->connector; - u8 tx[2] = { value & 0xff, value >> 8 }; - struct mipi_dsi_msg msg = { - .channel = 0, - .type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE, - .tx_len = sizeof(tx), - .tx_buf = tx, - }; - - if (!connector) - return -ENODEV; - - if (!connector->funcs || !connector->funcs->transfer) - return -ENOSYS; - - return connector->funcs->transfer(state, &msg); -} - -static bool mipi_dsi_packet_format_is_short(u8 type) -{ - switch (type) { - case MIPI_DSI_V_SYNC_START: - case MIPI_DSI_V_SYNC_END: - case MIPI_DSI_H_SYNC_START: - case MIPI_DSI_H_SYNC_END: - case MIPI_DSI_END_OF_TRANSMISSION: - case MIPI_DSI_COLOR_MODE_OFF: - case MIPI_DSI_COLOR_MODE_ON: - case MIPI_DSI_SHUTDOWN_PERIPHERAL: - case MIPI_DSI_TURN_ON_PERIPHERAL: - case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: - case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: - case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: - case MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM: - case MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM: - case MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM: - case MIPI_DSI_DCS_SHORT_WRITE: - case MIPI_DSI_DCS_SHORT_WRITE_PARAM: - case MIPI_DSI_DCS_READ: - case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE: - return true; - } - - return false; -} - -static bool mipi_dsi_packet_format_is_long(u8 type) -{ - switch (type) { - case MIPI_DSI_NULL_PACKET: - case MIPI_DSI_BLANKING_PACKET: - case MIPI_DSI_GENERIC_LONG_WRITE: - case MIPI_DSI_DCS_LONG_WRITE: - case MIPI_DSI_LOOSELY_PACKED_PIXEL_STREAM_YCBCR20: - case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR24: - case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR16: - case MIPI_DSI_PACKED_PIXEL_STREAM_30: - case MIPI_DSI_PACKED_PIXEL_STREAM_36: - case MIPI_DSI_PACKED_PIXEL_STREAM_YCBCR12: - case MIPI_DSI_PACKED_PIXEL_STREAM_16: - case MIPI_DSI_PACKED_PIXEL_STREAM_18: - case MIPI_DSI_PIXEL_STREAM_3BYTE_18: - case MIPI_DSI_PACKED_PIXEL_STREAM_24: - return true; - } - - return false; -} - -int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, - const struct mipi_dsi_msg *msg) -{ - if (!packet || !msg) - return -EINVAL; - - /* do some minimum sanity checking */ - if (!mipi_dsi_packet_format_is_short(msg->type) && - !mipi_dsi_packet_format_is_long(msg->type)) - return -EINVAL; - - if (msg->channel > 3) - return -EINVAL; - - memset(packet, 0, sizeof(*packet)); - packet->header[0] = ((msg->channel & 0x3) << 6) | (msg->type & 0x3f); - if (mipi_dsi_packet_format_is_long(msg->type)) { - packet->header[1] = (msg->tx_len >> 0) & 0xff; - packet->header[2] = (msg->tx_len >> 8) & 0xff; - packet->payload_length = msg->tx_len; - packet->payload = msg->tx_buf; - } else { - const u8 *tx = msg->tx_buf; - packet->header[1] = (msg->tx_len > 0) ? tx[0] : 0; - packet->header[2] = (msg->tx_len > 1) ? tx[1] : 0; - } - - packet->size = sizeof(packet->header) + packet->payload_length; - - return 0; -} diff --git a/drivers/video/drm/rockchip_mipi_dsi.h b/drivers/video/drm/rockchip_mipi_dsi.h deleted file mode 100644 index b3919a86a8..0000000000 --- a/drivers/video/drm/rockchip_mipi_dsi.h +++ /dev/null @@ -1,202 +0,0 @@ -/* - * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __ROCKCHIP_MIPI_DSI_H__ -#define __ROCKCHIP_MIPI_DSI_H__ - -#include - -#define MSEC_PER_SEC 1000L -#define USEC_PER_MSEC 1000L -#define NSEC_PER_USEC 1000L -#define NSEC_PER_MSEC 1000000L -#define USEC_PER_SEC 1000000L -#define NSEC_PER_SEC 1000000000L -#define FSEC_PER_SEC 1000000000000000LL - -#define GENMASK(h, l) (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) -#define UPDATE(v, h, l) (((v) << (l)) & GENMASK((h), (l))) -#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK(h, l) << 16)) - -#define readl_poll_timeout(addr, val, cond, sleep_us, timeout_us) \ -({ \ - int try = 100; \ - for (;;) { \ - (val) = readl(addr); \ - if (cond) \ - break; \ - try--; \ - if (!try) \ - break; \ - if (sleep_us) \ - udelay(sleep_us >> 2); \ - } \ - (cond) ? 0 : -ETIMEDOUT; \ -}) - -/* request ACK from peripheral */ -#define MIPI_DSI_MSG_REQ_ACK BIT(0) -/* use Low Power Mode to transmit message */ -#define MIPI_DSI_MSG_USE_LPM BIT(1) - -/** - * struct mipi_dsi_msg - read/write DSI buffer - * @channel: virtual channel id - * @type: payload data type - * @flags: flags controlling this message transmission - * @tx_len: length of @tx_buf - * @tx_buf: data to be written - * @rx_len: length of @rx_buf - * @rx_buf: data to be read, or NULL - */ -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; -}; - -/** - * struct mipi_dsi_packet - represents a MIPI DSI packet in protocol format - * @size: size (in bytes) of the packet - * @header: the four bytes that make up the header (Data ID, Word Count or - * Packet Data, and ECC) - * @payload_length: number of bytes in the payload - * @payload: a pointer to a buffer containing the payload, if any - */ -struct mipi_dsi_packet { - size_t size; - u8 header[4]; - size_t payload_length; - const u8 *payload; -}; - - -/* DSI mode flags */ - -/* video mode */ -#define MIPI_DSI_MODE_VIDEO BIT(0) -/* video burst mode */ -#define MIPI_DSI_MODE_VIDEO_BURST BIT(1) -/* video pulse mode */ -#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2) -/* enable auto vertical count mode */ -#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3) -/* enable hsync-end packets in vsync-pulse and v-porch area */ -#define MIPI_DSI_MODE_VIDEO_HSE BIT(4) -/* disable hfront-porch area */ -#define MIPI_DSI_MODE_VIDEO_HFP BIT(5) -/* disable hback-porch area */ -#define MIPI_DSI_MODE_VIDEO_HBP BIT(6) -/* disable hsync-active area */ -#define MIPI_DSI_MODE_VIDEO_HSA BIT(7) -/* flush display FIFO on vsync pulse */ -#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8) -/* disable EoT packets in HS mode */ -#define MIPI_DSI_MODE_EOT_PACKET BIT(9) -/* device supports non-continuous clock behavior (DSI spec 5.6.1) */ -#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10) -/* transmit data in low power */ -#define MIPI_DSI_MODE_LPM BIT(11) - -enum mipi_dsi_pixel_format { - MIPI_DSI_FMT_RGB888, - MIPI_DSI_FMT_RGB666, - MIPI_DSI_FMT_RGB666_PACKED, - MIPI_DSI_FMT_RGB565, -}; - -/** - * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any - * given pixel format defined by the MIPI DSI - * specification - * @fmt: MIPI DSI pixel format - * - * Returns: The number of bits per pixel of the given pixel format. - */ -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; -} - -/** - * enum mipi_dsi_dcs_tear_mode - Tearing Effect Output Line mode - * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking - * information only - * @MIPI_DSI_DCS_TEAR_MODE_VHBLANK : the TE output line consists of both - * V-Blanking and H-Blanking information - */ -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) - -struct mipi_dphy_timing { - unsigned int clkmiss; - unsigned int clkpost; - unsigned int clkpre; - unsigned int clkprepare; - unsigned int clksettle; - unsigned int clktermen; - unsigned int clktrail; - unsigned int clkzero; - unsigned int dtermen; - unsigned int eot; - unsigned int hsexit; - unsigned int hsprepare; - unsigned int hszero; - unsigned int hssettle; - unsigned int hsskip; - unsigned int hstrail; - unsigned int init; - unsigned int lpx; - unsigned int taget; - unsigned int tago; - unsigned int tasure; - unsigned int wakeup; -}; - -void mipi_dphy_timing_get_default(struct mipi_dphy_timing *timing, - unsigned long period); -ssize_t mipi_dsi_dcs_write(struct display_state *state, - const void *payload, size_t size); -ssize_t mipi_dsi_generic_write(struct display_state *state, - const void *payload, size_t size); -int mipi_dsi_create_packet(struct mipi_dsi_packet *packet, - const struct mipi_dsi_msg *msg); -ssize_t mipi_dsi_dcs_read(struct display_state *state, u8 cmd, void *data, - size_t len); -ssize_t mipi_dsi_generic_read(struct display_state *state, const void *params, - size_t num_params, void *data, size_t size); -ssize_t mipi_dsi_shutdown_peripheral(struct display_state *state); -ssize_t mipi_dsi_turn_on_peripheral(struct display_state *state); -int mipi_dsi_set_maximum_return_packet_size(struct display_state *state, - u16 value); -int mipi_dsi_dcs_get_pixel_format(struct display_state *state, u8 *format); -#endif /* __ROCKCHIP_MIPI_DSI__ */ diff --git a/drivers/video/drm/rockchip_panel.c b/drivers/video/drm/rockchip_panel.c index 8f953ee141..57bf479c74 100644 --- a/drivers/video/drm/rockchip_panel.c +++ b/drivers/video/drm/rockchip_panel.c @@ -4,6 +4,8 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include + #include #include #include @@ -21,7 +23,6 @@ #include "rockchip_display.h" #include "rockchip_crtc.h" #include "rockchip_connector.h" -#include "rockchip_mipi_dsi.h" #include "rockchip_panel.h" struct rockchip_cmd_header { @@ -209,7 +210,7 @@ static int rockchip_panel_send_spi_cmds(struct display_state *state, return 0; } -static int rockchip_panel_send_dsi_cmds(struct display_state *state, +static int rockchip_panel_send_dsi_cmds(struct mipi_dsi_device *dsi, struct rockchip_panel_cmds *cmds) { int i, ret; @@ -219,24 +220,25 @@ static int rockchip_panel_send_dsi_cmds(struct display_state *state, for (i = 0; i < cmds->cmd_cnt; i++) { struct rockchip_cmd_desc *desc = &cmds->cmds[i]; + const struct rockchip_cmd_header *header = &desc->header; - switch (desc->header.data_type) { + switch (header->data_type) { case MIPI_DSI_GENERIC_SHORT_WRITE_0_PARAM: case MIPI_DSI_GENERIC_SHORT_WRITE_1_PARAM: case MIPI_DSI_GENERIC_SHORT_WRITE_2_PARAM: case MIPI_DSI_GENERIC_LONG_WRITE: - ret = mipi_dsi_generic_write(state, desc->payload, - desc->header.payload_length); + ret = mipi_dsi_generic_write(dsi, desc->payload, + header->payload_length); break; case MIPI_DSI_DCS_SHORT_WRITE: case MIPI_DSI_DCS_SHORT_WRITE_PARAM: case MIPI_DSI_DCS_LONG_WRITE: - ret = mipi_dsi_dcs_write(state, desc->payload, - desc->header.payload_length); + ret = mipi_dsi_dcs_write_buffer(dsi, desc->payload, + header->payload_length); break; default: printf("unsupport command data type: %d\n", - desc->header.data_type); + header->data_type); return -EINVAL; } @@ -245,8 +247,8 @@ static int rockchip_panel_send_dsi_cmds(struct display_state *state, return ret; } - if (desc->header.delay_ms) - mdelay(desc->header.delay_ms); + if (header->delay_ms) + mdelay(header->delay_ms); } return 0; @@ -256,6 +258,7 @@ static void panel_simple_prepare(struct rockchip_panel *panel) { struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); + struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev); int ret; if (priv->prepared) @@ -290,8 +293,7 @@ static void panel_simple_prepare(struct rockchip_panel *panel) ret = rockchip_panel_send_mcu_cmds(panel->state, plat->on_cmds); else - ret = rockchip_panel_send_dsi_cmds(panel->state, - plat->on_cmds); + ret = rockchip_panel_send_dsi_cmds(dsi, plat->on_cmds); if (ret) printf("failed to send on cmds: %d\n", ret); } @@ -303,6 +305,7 @@ static void panel_simple_unprepare(struct rockchip_panel *panel) { struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev); struct rockchip_panel_priv *priv = dev_get_priv(panel->dev); + struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev); int ret; if (!priv->prepared) @@ -316,8 +319,7 @@ static void panel_simple_unprepare(struct rockchip_panel *panel) ret = rockchip_panel_send_mcu_cmds(panel->state, plat->off_cmds); else - ret = rockchip_panel_send_dsi_cmds(panel->state, - plat->off_cmds); + ret = rockchip_panel_send_dsi_cmds(dsi, plat->off_cmds); if (ret) printf("failed to send off cmds: %d\n", ret); } diff --git a/drivers/video/drm/rockchip_rgb.c b/drivers/video/drm/rockchip_rgb.c index 95fcad5023..60b09df21e 100644 --- a/drivers/video/drm/rockchip_rgb.c +++ b/drivers/video/drm/rockchip_rgb.c @@ -17,6 +17,8 @@ #include "rockchip_connector.h" #include "rockchip_phy.h" +#define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK(h, l) << 16)) + #define PX30_GRF_PD_VO_CON1 0x0438 #define PX30_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3) #define PX30_RGB_VOP_SEL(v) HIWORD_UPDATE(v, 2, 2) diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h new file mode 100644 index 0000000000..d05c07b7f5 --- /dev/null +++ b/include/drm/drm_mipi_dsi.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * MIPI DSI Bus + * + * Copyright (C) 2012-2013, Samsung Electronics, Co., Ltd. + * Andrzej Hajda + */ + +#ifndef __DRM_MIPI_DSI_H__ +#define __DRM_MIPI_DSI_H__ + +#include +#include + +struct mipi_dsi_host; +struct mipi_dsi_device; + +/* request ACK from peripheral */ +#define MIPI_DSI_MSG_REQ_ACK BIT(0) +/* use Low Power Mode to transmit message */ +#define MIPI_DSI_MSG_USE_LPM BIT(1) + +/** + * struct mipi_dsi_msg - read/write DSI buffer + * @channel: virtual channel id + * @type: payload data type + * @flags: flags controlling this message transmission + * @tx_len: length of @tx_buf + * @tx_buf: data to be written + * @rx_len: length of @rx_buf + * @rx_buf: data to be read, or NULL + */ +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 - represents a MIPI DSI packet in protocol format + * @size: size (in bytes) of the packet + * @header: the four bytes that make up the header (Data ID, Word Count or + * Packet Data, and ECC) + * @payload_length: number of bytes in the payload + * @payload: a pointer to a buffer containing the payload, if any + */ +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 - DSI bus operations + * @attach: attach DSI device to DSI host + * @detach: detach DSI device from DSI host + * @transfer: transmit a DSI packet + * + * DSI packets transmitted by .transfer() are passed in as mipi_dsi_msg + * structures. This structure contains information about the type of packet + * being transmitted as well as the transmit and receive buffers. When an + * error is encountered during transmission, this function will return a + * negative error code. On success it shall return the number of bytes + * transmitted for write packets or the number of bytes received for read + * packets. + * + * Note that typically DSI packet transmission is atomic, so the .transfer() + * function will seldomly return anything other than the number of bytes + * contained in the transmit buffer on success. + */ +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 - DSI host device + * @dev: driver model device node for this DSI host + * @ops: DSI host operations + * @list: list management + */ +struct mipi_dsi_host { + struct udevice *dev; + const struct mipi_dsi_host_ops *ops; +}; + +/* DSI mode flags */ + +/* video mode */ +#define MIPI_DSI_MODE_VIDEO BIT(0) +/* video burst mode */ +#define MIPI_DSI_MODE_VIDEO_BURST BIT(1) +/* video pulse mode */ +#define MIPI_DSI_MODE_VIDEO_SYNC_PULSE BIT(2) +/* enable auto vertical count mode */ +#define MIPI_DSI_MODE_VIDEO_AUTO_VERT BIT(3) +/* enable hsync-end packets in vsync-pulse and v-porch area */ +#define MIPI_DSI_MODE_VIDEO_HSE BIT(4) +/* disable hfront-porch area */ +#define MIPI_DSI_MODE_VIDEO_HFP BIT(5) +/* disable hback-porch area */ +#define MIPI_DSI_MODE_VIDEO_HBP BIT(6) +/* disable hsync-active area */ +#define MIPI_DSI_MODE_VIDEO_HSA BIT(7) +/* flush display FIFO on vsync pulse */ +#define MIPI_DSI_MODE_VSYNC_FLUSH BIT(8) +/* disable EoT packets in HS mode */ +#define MIPI_DSI_MODE_EOT_PACKET BIT(9) +/* device supports non-continuous clock behavior (DSI spec 5.6.1) */ +#define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10) +/* transmit data in low power */ +#define MIPI_DSI_MODE_LPM BIT(11) + +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 - DSI peripheral device + * @host: DSI host for this peripheral + * @dev: driver model device node for this peripheral + * @name: DSI peripheral chip type + * @channel: virtual channel assigned to the peripheral + * @format: pixel format for video mode + * @lanes: number of active data lanes + * @mode_flags: DSI operation mode related flags + * @hs_rate: maximum lane frequency for high speed mode in hertz, this should + * be set to the real limits of the hardware, zero is only accepted for + * legacy drivers + * @lp_rate: maximum lane frequency for low power mode in hertz, this should + * be set to the real limits of the hardware, zero is only accepted for + * legacy drivers + */ +struct mipi_dsi_device { + struct mipi_dsi_host *host; + struct udevice *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; +}; + +/** + * mipi_dsi_pixel_format_to_bpp - obtain the number of bits per pixel for any + * given pixel format defined by the MIPI DSI + * specification + * @fmt: MIPI DSI pixel format + * + * Returns: The number of bits per pixel of the given pixel format. + */ +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; +} + +int mipi_dsi_attach(struct mipi_dsi_device *dsi); +int mipi_dsi_detach(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_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 - Tearing Effect Output Line mode + * @MIPI_DSI_DCS_TEAR_MODE_VBLANK: the TE output line consists of V-Blanking + * information only + * @MIPI_DSI_DCS_TEAR_MODE_VHBLANK : the TE output line consists of both + * V-Blanking and H-Blanking information + */ +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 BIT(2) +#define MIPI_DSI_DCS_POWER_MODE_NORMAL BIT(3) +#define MIPI_DSI_DCS_POWER_MODE_SLEEP BIT(4) +#define MIPI_DSI_DCS_POWER_MODE_PARTIAL BIT(5) +#define MIPI_DSI_DCS_POWER_MODE_IDLE BIT(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); + +#endif /* __DRM_MIPI_DSI__ */