@@ -4231,6 +4231,7 @@ enum skl_disp_power_wells {
#define PIPECONF_INTERLACED_DBL_ILK (4 << 21) /* ilk/snb only */
#define PIPECONF_PFIT_PF_INTERLACED_DBL_ILK (5 << 21) /* ilk/snb only */
#define PIPECONF_INTERLACE_MODE_MASK (7 << 21)
+#define PIPECONF_MIPI_DSR_ENABLE (1 << 20)
#define PIPECONF_EDP_RR_MODE_SWITCH (1 << 20)
#define PIPECONF_CXSR_DOWNCLOCK (1<<16)
#define PIPECONF_EDP_RR_MODE_SWITCH_VLV (1 << 14)
@@ -1197,6 +1197,7 @@ void intel_dp_mst_encoder_cleanup(struct intel_digital_port *intel_dig_port);
/* intel_dsi.c */
void intel_dsi_init(struct drm_device *dev);
+void intel_dsi_update_panel_fb(struct intel_encoder *encoder);
/* intel_dvo.c */
void intel_dvo_init(struct drm_device *dev);
@@ -31,6 +31,7 @@
#include <drm/drm_panel.h>
#include <drm/drm_mipi_dsi.h>
#include <linux/slab.h>
+#include <video/mipi_display.h>
#include "i915_drv.h"
#include "intel_drv.h"
#include "intel_dsi.h"
@@ -202,6 +203,41 @@ static struct intel_dsi_host *intel_dsi_host_init(struct intel_dsi *intel_dsi,
return host;
}
+int dsi_send_dcs_cmd(struct intel_dsi *intel_dsi, int channel, const u8 *data,
+ int len, bool pipe_render)
+{
+ struct drm_encoder *encoder = &intel_dsi->base.base;
+ struct drm_device *dev = encoder->dev;
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ enum port port;
+ u32 cmd_addr;
+
+ for_each_dsi_port(port, intel_dsi->ports) {
+ if (I915_READ(MIPI_COMMAND_ADDRESS(port)) & COMMAND_VALID)
+ return -EBUSY;
+
+ if ((I915_READ(PIPECONF(port)) & PIPECONF_MIPI_DSR_ENABLE) == 0)
+ return -EBUSY;
+
+ if (!intel_dsi->cmd_buff)
+ return -ENOMEM;
+
+ memcpy(intel_dsi->cmd_buff, data, len);
+
+ cmd_addr = intel_dsi->cmd_buff_phy_addr &
+ COMMAND_MEM_ADDRESS_MASK;
+ cmd_addr |= COMMAND_VALID;
+
+ if (pipe_render)
+ cmd_addr |= MEMORY_WRITE_DATA_FROM_PIPE_RENDERING;
+
+ I915_WRITE(MIPI_COMMAND_LENGTH(port), len);
+ I915_WRITE(MIPI_COMMAND_ADDRESS(port), cmd_addr);
+ }
+
+ return 0;
+}
+
/*
* send a video mode command
*
@@ -667,6 +703,14 @@ static void intel_dsi_get_config(struct intel_encoder *encoder,
pipe_config->port_clock = pclk;
}
+void intel_dsi_update_panel_fb(struct intel_encoder *encoder)
+{
+ struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
+ unsigned char uc_data[] = {MIPI_DCS_WRITE_MEMORY_START};
+
+ dsi_send_dcs_cmd(intel_dsi, 0, uc_data, sizeof(uc_data), true);
+}
+
static enum drm_mode_status
intel_dsi_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)