0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include <drm/drm_mipi_dsi.h>
0027 #include <video/mipi_display.h>
0028
0029 #include "i915_drv.h"
0030 #include "intel_display_types.h"
0031 #include "intel_dsi.h"
0032 #include "intel_dsi_dcs_backlight.h"
0033
0034 #define CONTROL_DISPLAY_BCTRL (1 << 5)
0035 #define CONTROL_DISPLAY_DD (1 << 3)
0036 #define CONTROL_DISPLAY_BL (1 << 2)
0037
0038 #define POWER_SAVE_OFF (0 << 0)
0039 #define POWER_SAVE_LOW (1 << 0)
0040 #define POWER_SAVE_MEDIUM (2 << 0)
0041 #define POWER_SAVE_HIGH (3 << 0)
0042 #define POWER_SAVE_OUTDOOR_MODE (4 << 0)
0043
0044 #define PANEL_PWM_MAX_VALUE 0xFF
0045
0046 static u32 dcs_get_backlight(struct intel_connector *connector, enum pipe unused)
0047 {
0048 struct intel_encoder *encoder = intel_attached_encoder(connector);
0049 struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
0050 struct intel_panel *panel = &connector->panel;
0051 struct mipi_dsi_device *dsi_device;
0052 u8 data[2] = {};
0053 enum port port;
0054 size_t len = panel->backlight.max > U8_MAX ? 2 : 1;
0055
0056 for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
0057 dsi_device = intel_dsi->dsi_hosts[port]->device;
0058 mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
0059 &data, len);
0060 break;
0061 }
0062
0063 return (data[1] << 8) | data[0];
0064 }
0065
0066 static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 level)
0067 {
0068 struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
0069 struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
0070 struct mipi_dsi_device *dsi_device;
0071 u8 data[2] = {};
0072 enum port port;
0073 size_t len = panel->backlight.max > U8_MAX ? 2 : 1;
0074 unsigned long mode_flags;
0075
0076 if (len == 1) {
0077 data[0] = level;
0078 } else {
0079 data[0] = level >> 8;
0080 data[1] = level;
0081 }
0082
0083 for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
0084 dsi_device = intel_dsi->dsi_hosts[port]->device;
0085 mode_flags = dsi_device->mode_flags;
0086 dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM;
0087 mipi_dsi_dcs_write(dsi_device, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
0088 &data, len);
0089 dsi_device->mode_flags = mode_flags;
0090 }
0091 }
0092
0093 static void dcs_disable_backlight(const struct drm_connector_state *conn_state, u32 level)
0094 {
0095 struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
0096 struct mipi_dsi_device *dsi_device;
0097 enum port port;
0098
0099 dcs_set_backlight(conn_state, 0);
0100
0101 for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
0102 u8 cabc = POWER_SAVE_OFF;
0103
0104 dsi_device = intel_dsi->dsi_hosts[port]->device;
0105 mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
0106 &cabc, sizeof(cabc));
0107 }
0108
0109 for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
0110 u8 ctrl = 0;
0111
0112 dsi_device = intel_dsi->dsi_hosts[port]->device;
0113
0114 mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_CONTROL_DISPLAY,
0115 &ctrl, sizeof(ctrl));
0116
0117 ctrl &= ~CONTROL_DISPLAY_BL;
0118 ctrl &= ~CONTROL_DISPLAY_DD;
0119 ctrl &= ~CONTROL_DISPLAY_BCTRL;
0120
0121 mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_CONTROL_DISPLAY,
0122 &ctrl, sizeof(ctrl));
0123 }
0124 }
0125
0126 static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state,
0127 const struct drm_connector_state *conn_state, u32 level)
0128 {
0129 struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
0130 struct mipi_dsi_device *dsi_device;
0131 enum port port;
0132
0133 for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
0134 u8 ctrl = 0;
0135
0136 dsi_device = intel_dsi->dsi_hosts[port]->device;
0137
0138 mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_CONTROL_DISPLAY,
0139 &ctrl, sizeof(ctrl));
0140
0141 ctrl |= CONTROL_DISPLAY_BL;
0142 ctrl |= CONTROL_DISPLAY_DD;
0143 ctrl |= CONTROL_DISPLAY_BCTRL;
0144
0145 mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_CONTROL_DISPLAY,
0146 &ctrl, sizeof(ctrl));
0147 }
0148
0149 for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
0150 u8 cabc = POWER_SAVE_MEDIUM;
0151
0152 dsi_device = intel_dsi->dsi_hosts[port]->device;
0153 mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
0154 &cabc, sizeof(cabc));
0155 }
0156
0157 dcs_set_backlight(conn_state, level);
0158 }
0159
0160 static int dcs_setup_backlight(struct intel_connector *connector,
0161 enum pipe unused)
0162 {
0163 struct intel_panel *panel = &connector->panel;
0164
0165 if (panel->vbt.backlight.brightness_precision_bits > 8)
0166 panel->backlight.max = (1 << panel->vbt.backlight.brightness_precision_bits) - 1;
0167 else
0168 panel->backlight.max = PANEL_PWM_MAX_VALUE;
0169
0170 panel->backlight.level = panel->backlight.max;
0171
0172 return 0;
0173 }
0174
0175 static const struct intel_panel_bl_funcs dcs_bl_funcs = {
0176 .setup = dcs_setup_backlight,
0177 .enable = dcs_enable_backlight,
0178 .disable = dcs_disable_backlight,
0179 .set = dcs_set_backlight,
0180 .get = dcs_get_backlight,
0181 };
0182
0183 int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector)
0184 {
0185 struct drm_device *dev = intel_connector->base.dev;
0186 struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
0187 struct intel_panel *panel = &intel_connector->panel;
0188
0189 if (panel->vbt.backlight.type != INTEL_BACKLIGHT_DSI_DCS)
0190 return -ENODEV;
0191
0192 if (drm_WARN_ON(dev, encoder->type != INTEL_OUTPUT_DSI))
0193 return -EINVAL;
0194
0195 panel->backlight.funcs = &dcs_bl_funcs;
0196
0197 return 0;
0198 }