11487f786SFrançois Tigeot /*
21487f786SFrançois Tigeot * Copyright © 2016 Intel Corporation
31487f786SFrançois Tigeot *
41487f786SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a
51487f786SFrançois Tigeot * copy of this software and associated documentation files (the "Software"),
61487f786SFrançois Tigeot * to deal in the Software without restriction, including without limitation
71487f786SFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense,
81487f786SFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the
91487f786SFrançois Tigeot * Software is furnished to do so, subject to the following conditions:
101487f786SFrançois Tigeot *
111487f786SFrançois Tigeot * The above copyright notice and this permission notice (including the next
121487f786SFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the
131487f786SFrançois Tigeot * Software.
141487f786SFrançois Tigeot *
151487f786SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161487f786SFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171487f786SFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
181487f786SFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191487f786SFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
201487f786SFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
211487f786SFrançois Tigeot * DEALINGS IN THE SOFTWARE.
221487f786SFrançois Tigeot *
231487f786SFrançois Tigeot * Author: Deepak M <m.deepak at intel.com>
241487f786SFrançois Tigeot */
251487f786SFrançois Tigeot
261487f786SFrançois Tigeot #include "intel_drv.h"
271487f786SFrançois Tigeot #include "intel_dsi.h"
281487f786SFrançois Tigeot #include "i915_drv.h"
291487f786SFrançois Tigeot #include <video/mipi_display.h>
301487f786SFrançois Tigeot #include <drm/drm_mipi_dsi.h>
311487f786SFrançois Tigeot
321487f786SFrançois Tigeot #define CONTROL_DISPLAY_BCTRL (1 << 5)
331487f786SFrançois Tigeot #define CONTROL_DISPLAY_DD (1 << 3)
341487f786SFrançois Tigeot #define CONTROL_DISPLAY_BL (1 << 2)
351487f786SFrançois Tigeot
361487f786SFrançois Tigeot #define POWER_SAVE_OFF (0 << 0)
371487f786SFrançois Tigeot #define POWER_SAVE_LOW (1 << 0)
381487f786SFrançois Tigeot #define POWER_SAVE_MEDIUM (2 << 0)
391487f786SFrançois Tigeot #define POWER_SAVE_HIGH (3 << 0)
401487f786SFrançois Tigeot #define POWER_SAVE_OUTDOOR_MODE (4 << 0)
411487f786SFrançois Tigeot
421487f786SFrançois Tigeot #define PANEL_PWM_MAX_VALUE 0xFF
431487f786SFrançois Tigeot
dcs_get_backlight(struct intel_connector * connector)441487f786SFrançois Tigeot static u32 dcs_get_backlight(struct intel_connector *connector)
451487f786SFrançois Tigeot {
461487f786SFrançois Tigeot struct intel_encoder *encoder = connector->encoder;
471487f786SFrançois Tigeot struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
481487f786SFrançois Tigeot struct mipi_dsi_device *dsi_device;
49*3f2dd94aSFrançois Tigeot u8 data = 0;
501487f786SFrançois Tigeot enum port port;
511487f786SFrançois Tigeot
521487f786SFrançois Tigeot /* FIXME: Need to take care of 16 bit brightness level */
531487f786SFrançois Tigeot for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
541487f786SFrançois Tigeot dsi_device = intel_dsi->dsi_hosts[port]->device;
551487f786SFrançois Tigeot mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
561487f786SFrançois Tigeot &data, sizeof(data));
571487f786SFrançois Tigeot break;
581487f786SFrançois Tigeot }
591487f786SFrançois Tigeot
601487f786SFrançois Tigeot return data;
611487f786SFrançois Tigeot }
621487f786SFrançois Tigeot
dcs_set_backlight(const struct drm_connector_state * conn_state,u32 level)63*3f2dd94aSFrançois Tigeot static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 level)
641487f786SFrançois Tigeot {
65*3f2dd94aSFrançois Tigeot struct intel_dsi *intel_dsi = enc_to_intel_dsi(conn_state->best_encoder);
661487f786SFrançois Tigeot struct mipi_dsi_device *dsi_device;
671487f786SFrançois Tigeot u8 data = level;
681487f786SFrançois Tigeot enum port port;
691487f786SFrançois Tigeot
701487f786SFrançois Tigeot /* FIXME: Need to take care of 16 bit brightness level */
711487f786SFrançois Tigeot for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
721487f786SFrançois Tigeot dsi_device = intel_dsi->dsi_hosts[port]->device;
731487f786SFrançois Tigeot mipi_dsi_dcs_write(dsi_device, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
741487f786SFrançois Tigeot &data, sizeof(data));
751487f786SFrançois Tigeot }
761487f786SFrançois Tigeot }
771487f786SFrançois Tigeot
dcs_disable_backlight(const struct drm_connector_state * conn_state)78*3f2dd94aSFrançois Tigeot static void dcs_disable_backlight(const struct drm_connector_state *conn_state)
791487f786SFrançois Tigeot {
80*3f2dd94aSFrançois Tigeot struct intel_dsi *intel_dsi = enc_to_intel_dsi(conn_state->best_encoder);
811487f786SFrançois Tigeot struct mipi_dsi_device *dsi_device;
821487f786SFrançois Tigeot enum port port;
831487f786SFrançois Tigeot
84*3f2dd94aSFrançois Tigeot dcs_set_backlight(conn_state, 0);
851487f786SFrançois Tigeot
861487f786SFrançois Tigeot for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
871487f786SFrançois Tigeot u8 cabc = POWER_SAVE_OFF;
881487f786SFrançois Tigeot
891487f786SFrançois Tigeot dsi_device = intel_dsi->dsi_hosts[port]->device;
901487f786SFrançois Tigeot mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
911487f786SFrançois Tigeot &cabc, sizeof(cabc));
921487f786SFrançois Tigeot }
931487f786SFrançois Tigeot
941487f786SFrançois Tigeot for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
951487f786SFrançois Tigeot u8 ctrl = 0;
961487f786SFrançois Tigeot
971487f786SFrançois Tigeot dsi_device = intel_dsi->dsi_hosts[port]->device;
981487f786SFrançois Tigeot
991487f786SFrançois Tigeot mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_CONTROL_DISPLAY,
1001487f786SFrançois Tigeot &ctrl, sizeof(ctrl));
1011487f786SFrançois Tigeot
1021487f786SFrançois Tigeot ctrl &= ~CONTROL_DISPLAY_BL;
1031487f786SFrançois Tigeot ctrl &= ~CONTROL_DISPLAY_DD;
1041487f786SFrançois Tigeot ctrl &= ~CONTROL_DISPLAY_BCTRL;
1051487f786SFrançois Tigeot
1061487f786SFrançois Tigeot mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_CONTROL_DISPLAY,
1071487f786SFrançois Tigeot &ctrl, sizeof(ctrl));
1081487f786SFrançois Tigeot }
1091487f786SFrançois Tigeot }
1101487f786SFrançois Tigeot
dcs_enable_backlight(const struct intel_crtc_state * crtc_state,const struct drm_connector_state * conn_state)111*3f2dd94aSFrançois Tigeot static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state,
112*3f2dd94aSFrançois Tigeot const struct drm_connector_state *conn_state)
1131487f786SFrançois Tigeot {
114*3f2dd94aSFrançois Tigeot struct intel_dsi *intel_dsi = enc_to_intel_dsi(conn_state->best_encoder);
115*3f2dd94aSFrançois Tigeot struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
1161487f786SFrançois Tigeot struct mipi_dsi_device *dsi_device;
1171487f786SFrançois Tigeot enum port port;
1181487f786SFrançois Tigeot
1191487f786SFrançois Tigeot for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
1201487f786SFrançois Tigeot u8 ctrl = 0;
1211487f786SFrançois Tigeot
1221487f786SFrançois Tigeot dsi_device = intel_dsi->dsi_hosts[port]->device;
1231487f786SFrançois Tigeot
1241487f786SFrançois Tigeot mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_CONTROL_DISPLAY,
1251487f786SFrançois Tigeot &ctrl, sizeof(ctrl));
1261487f786SFrançois Tigeot
1271487f786SFrançois Tigeot ctrl |= CONTROL_DISPLAY_BL;
1281487f786SFrançois Tigeot ctrl |= CONTROL_DISPLAY_DD;
1291487f786SFrançois Tigeot ctrl |= CONTROL_DISPLAY_BCTRL;
1301487f786SFrançois Tigeot
1311487f786SFrançois Tigeot mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_CONTROL_DISPLAY,
1321487f786SFrançois Tigeot &ctrl, sizeof(ctrl));
1331487f786SFrançois Tigeot }
1341487f786SFrançois Tigeot
1351487f786SFrançois Tigeot for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
1361487f786SFrançois Tigeot u8 cabc = POWER_SAVE_MEDIUM;
1371487f786SFrançois Tigeot
1381487f786SFrançois Tigeot dsi_device = intel_dsi->dsi_hosts[port]->device;
1391487f786SFrançois Tigeot mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
1401487f786SFrançois Tigeot &cabc, sizeof(cabc));
1411487f786SFrançois Tigeot }
1421487f786SFrançois Tigeot
143*3f2dd94aSFrançois Tigeot dcs_set_backlight(conn_state, panel->backlight.level);
1441487f786SFrançois Tigeot }
1451487f786SFrançois Tigeot
dcs_setup_backlight(struct intel_connector * connector,enum i915_pipe unused)1461487f786SFrançois Tigeot static int dcs_setup_backlight(struct intel_connector *connector,
1471487f786SFrançois Tigeot enum i915_pipe unused)
1481487f786SFrançois Tigeot {
1491487f786SFrançois Tigeot struct intel_panel *panel = &connector->panel;
1501487f786SFrançois Tigeot
1511487f786SFrançois Tigeot panel->backlight.max = PANEL_PWM_MAX_VALUE;
1521487f786SFrançois Tigeot panel->backlight.level = PANEL_PWM_MAX_VALUE;
1531487f786SFrançois Tigeot
1541487f786SFrançois Tigeot return 0;
1551487f786SFrançois Tigeot }
1561487f786SFrançois Tigeot
intel_dsi_dcs_init_backlight_funcs(struct intel_connector * intel_connector)1571487f786SFrançois Tigeot int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector)
1581487f786SFrançois Tigeot {
1591487f786SFrançois Tigeot struct drm_device *dev = intel_connector->base.dev;
160303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev);
1611487f786SFrançois Tigeot struct intel_encoder *encoder = intel_connector->encoder;
1621487f786SFrançois Tigeot struct intel_panel *panel = &intel_connector->panel;
1631487f786SFrançois Tigeot
1641487f786SFrançois Tigeot if (dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_DSI_DCS)
1651487f786SFrançois Tigeot return -ENODEV;
1661487f786SFrançois Tigeot
1671487f786SFrançois Tigeot if (WARN_ON(encoder->type != INTEL_OUTPUT_DSI))
1681487f786SFrançois Tigeot return -EINVAL;
1691487f786SFrançois Tigeot
1701487f786SFrançois Tigeot panel->backlight.setup = dcs_setup_backlight;
1711487f786SFrançois Tigeot panel->backlight.enable = dcs_enable_backlight;
1721487f786SFrançois Tigeot panel->backlight.disable = dcs_disable_backlight;
1731487f786SFrançois Tigeot panel->backlight.set = dcs_set_backlight;
1741487f786SFrançois Tigeot panel->backlight.get = dcs_get_backlight;
1751487f786SFrançois Tigeot
1761487f786SFrançois Tigeot return 0;
1771487f786SFrançois Tigeot }
178