cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_dsi_dcs_backlight.c (6317B)


      1/*
      2 * Copyright © 2016 Intel Corporation
      3 *
      4 * Permission is hereby granted, free of charge, to any person obtaining a
      5 * copy of this software and associated documentation files (the "Software"),
      6 * to deal in the Software without restriction, including without limitation
      7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 * and/or sell copies of the Software, and to permit persons to whom the
      9 * Software is furnished to do so, subject to the following conditions:
     10 *
     11 * The above copyright notice and this permission notice (including the next
     12 * paragraph) shall be included in all copies or substantial portions of the
     13 * Software.
     14 *
     15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 * DEALINGS IN THE SOFTWARE.
     22 *
     23 * Author: Deepak M <m.deepak at intel.com>
     24 */
     25
     26#include <drm/drm_mipi_dsi.h>
     27#include <video/mipi_display.h>
     28
     29#include "i915_drv.h"
     30#include "intel_display_types.h"
     31#include "intel_dsi.h"
     32#include "intel_dsi_dcs_backlight.h"
     33
     34#define CONTROL_DISPLAY_BCTRL		(1 << 5)
     35#define CONTROL_DISPLAY_DD		(1 << 3)
     36#define CONTROL_DISPLAY_BL		(1 << 2)
     37
     38#define POWER_SAVE_OFF			(0 << 0)
     39#define POWER_SAVE_LOW			(1 << 0)
     40#define POWER_SAVE_MEDIUM		(2 << 0)
     41#define POWER_SAVE_HIGH			(3 << 0)
     42#define POWER_SAVE_OUTDOOR_MODE		(4 << 0)
     43
     44#define PANEL_PWM_MAX_VALUE		0xFF
     45
     46static u32 dcs_get_backlight(struct intel_connector *connector, enum pipe unused)
     47{
     48	struct intel_encoder *encoder = intel_attached_encoder(connector);
     49	struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder);
     50	struct intel_panel *panel = &connector->panel;
     51	struct mipi_dsi_device *dsi_device;
     52	u8 data[2] = {};
     53	enum port port;
     54	size_t len = panel->backlight.max > U8_MAX ? 2 : 1;
     55
     56	for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
     57		dsi_device = intel_dsi->dsi_hosts[port]->device;
     58		mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
     59				  &data, len);
     60		break;
     61	}
     62
     63	return (data[1] << 8) | data[0];
     64}
     65
     66static void dcs_set_backlight(const struct drm_connector_state *conn_state, u32 level)
     67{
     68	struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
     69	struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
     70	struct mipi_dsi_device *dsi_device;
     71	u8 data[2] = {};
     72	enum port port;
     73	size_t len = panel->backlight.max > U8_MAX ? 2 : 1;
     74	unsigned long mode_flags;
     75
     76	if (len == 1) {
     77		data[0] = level;
     78	} else {
     79		data[0] = level >> 8;
     80		data[1] = level;
     81	}
     82
     83	for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
     84		dsi_device = intel_dsi->dsi_hosts[port]->device;
     85		mode_flags = dsi_device->mode_flags;
     86		dsi_device->mode_flags &= ~MIPI_DSI_MODE_LPM;
     87		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
     88				   &data, len);
     89		dsi_device->mode_flags = mode_flags;
     90	}
     91}
     92
     93static void dcs_disable_backlight(const struct drm_connector_state *conn_state, u32 level)
     94{
     95	struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
     96	struct mipi_dsi_device *dsi_device;
     97	enum port port;
     98
     99	dcs_set_backlight(conn_state, 0);
    100
    101	for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
    102		u8 cabc = POWER_SAVE_OFF;
    103
    104		dsi_device = intel_dsi->dsi_hosts[port]->device;
    105		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
    106				   &cabc, sizeof(cabc));
    107	}
    108
    109	for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
    110		u8 ctrl = 0;
    111
    112		dsi_device = intel_dsi->dsi_hosts[port]->device;
    113
    114		mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_CONTROL_DISPLAY,
    115				  &ctrl, sizeof(ctrl));
    116
    117		ctrl &= ~CONTROL_DISPLAY_BL;
    118		ctrl &= ~CONTROL_DISPLAY_DD;
    119		ctrl &= ~CONTROL_DISPLAY_BCTRL;
    120
    121		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_CONTROL_DISPLAY,
    122				   &ctrl, sizeof(ctrl));
    123	}
    124}
    125
    126static void dcs_enable_backlight(const struct intel_crtc_state *crtc_state,
    127				 const struct drm_connector_state *conn_state, u32 level)
    128{
    129	struct intel_dsi *intel_dsi = enc_to_intel_dsi(to_intel_encoder(conn_state->best_encoder));
    130	struct mipi_dsi_device *dsi_device;
    131	enum port port;
    132
    133	for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
    134		u8 ctrl = 0;
    135
    136		dsi_device = intel_dsi->dsi_hosts[port]->device;
    137
    138		mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_CONTROL_DISPLAY,
    139				  &ctrl, sizeof(ctrl));
    140
    141		ctrl |= CONTROL_DISPLAY_BL;
    142		ctrl |= CONTROL_DISPLAY_DD;
    143		ctrl |= CONTROL_DISPLAY_BCTRL;
    144
    145		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_CONTROL_DISPLAY,
    146				   &ctrl, sizeof(ctrl));
    147	}
    148
    149	for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
    150		u8 cabc = POWER_SAVE_MEDIUM;
    151
    152		dsi_device = intel_dsi->dsi_hosts[port]->device;
    153		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
    154				   &cabc, sizeof(cabc));
    155	}
    156
    157	dcs_set_backlight(conn_state, level);
    158}
    159
    160static int dcs_setup_backlight(struct intel_connector *connector,
    161			       enum pipe unused)
    162{
    163	struct drm_device *dev = connector->base.dev;
    164	struct drm_i915_private *dev_priv = to_i915(dev);
    165	struct intel_panel *panel = &connector->panel;
    166
    167	if (dev_priv->vbt.backlight.brightness_precision_bits > 8)
    168		panel->backlight.max = (1 << dev_priv->vbt.backlight.brightness_precision_bits) - 1;
    169	else
    170		panel->backlight.max = PANEL_PWM_MAX_VALUE;
    171
    172	panel->backlight.level = panel->backlight.max;
    173
    174	return 0;
    175}
    176
    177static const struct intel_panel_bl_funcs dcs_bl_funcs = {
    178	.setup = dcs_setup_backlight,
    179	.enable = dcs_enable_backlight,
    180	.disable = dcs_disable_backlight,
    181	.set = dcs_set_backlight,
    182	.get = dcs_get_backlight,
    183};
    184
    185int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector)
    186{
    187	struct drm_device *dev = intel_connector->base.dev;
    188	struct drm_i915_private *dev_priv = to_i915(dev);
    189	struct intel_encoder *encoder = intel_attached_encoder(intel_connector);
    190	struct intel_panel *panel = &intel_connector->panel;
    191
    192	if (dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_DSI_DCS)
    193		return -ENODEV;
    194
    195	if (drm_WARN_ON(dev, encoder->type != INTEL_OUTPUT_DSI))
    196		return -EINVAL;
    197
    198	panel->backlight.funcs = &dcs_bl_funcs;
    199
    200	return 0;
    201}