Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  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 "intel_drv.h"
 27#include "intel_dsi.h"
 28#include "i915_drv.h"
 29#include <video/mipi_display.h>
 30#include <drm/drm_mipi_dsi.h>
 31
 32#define CONTROL_DISPLAY_BCTRL		(1 << 5)
 33#define CONTROL_DISPLAY_DD		(1 << 3)
 34#define CONTROL_DISPLAY_BL		(1 << 2)
 35
 36#define POWER_SAVE_OFF			(0 << 0)
 37#define POWER_SAVE_LOW			(1 << 0)
 38#define POWER_SAVE_MEDIUM		(2 << 0)
 39#define POWER_SAVE_HIGH			(3 << 0)
 40#define POWER_SAVE_OUTDOOR_MODE		(4 << 0)
 41
 42#define PANEL_PWM_MAX_VALUE		0xFF
 43
 44static u32 dcs_get_backlight(struct intel_connector *connector)
 45{
 46	struct intel_encoder *encoder = connector->encoder;
 47	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
 48	struct mipi_dsi_device *dsi_device;
 49	u8 data;
 50	enum port port;
 51
 52	/* FIXME: Need to take care of 16 bit brightness level */
 53	for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
 54		dsi_device = intel_dsi->dsi_hosts[port]->device;
 55		mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_DISPLAY_BRIGHTNESS,
 56				  &data, sizeof(data));
 57		break;
 58	}
 59
 60	return data;
 61}
 62
 63static void dcs_set_backlight(struct intel_connector *connector, u32 level)
 64{
 65	struct intel_encoder *encoder = connector->encoder;
 66	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
 67	struct mipi_dsi_device *dsi_device;
 68	u8 data = level;
 69	enum port port;
 70
 71	/* FIXME: Need to take care of 16 bit brightness level */
 72	for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
 73		dsi_device = intel_dsi->dsi_hosts[port]->device;
 74		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_SET_DISPLAY_BRIGHTNESS,
 75				   &data, sizeof(data));
 76	}
 77}
 78
 79static void dcs_disable_backlight(struct intel_connector *connector)
 80{
 81	struct intel_encoder *encoder = connector->encoder;
 82	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
 83	struct mipi_dsi_device *dsi_device;
 84	enum port port;
 85
 86	dcs_set_backlight(connector, 0);
 87
 88	for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
 89		u8 cabc = POWER_SAVE_OFF;
 90
 91		dsi_device = intel_dsi->dsi_hosts[port]->device;
 92		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
 93				   &cabc, sizeof(cabc));
 94	}
 95
 96	for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
 97		u8 ctrl = 0;
 98
 99		dsi_device = intel_dsi->dsi_hosts[port]->device;
100
101		mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_CONTROL_DISPLAY,
102				  &ctrl, sizeof(ctrl));
103
104		ctrl &= ~CONTROL_DISPLAY_BL;
105		ctrl &= ~CONTROL_DISPLAY_DD;
106		ctrl &= ~CONTROL_DISPLAY_BCTRL;
107
108		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_CONTROL_DISPLAY,
109				   &ctrl, sizeof(ctrl));
110	}
111}
112
113static void dcs_enable_backlight(struct intel_connector *connector)
114{
115	struct intel_encoder *encoder = connector->encoder;
116	struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
117	struct intel_panel *panel = &connector->panel;
118	struct mipi_dsi_device *dsi_device;
119	enum port port;
120
121	for_each_dsi_port(port, intel_dsi->dcs_backlight_ports) {
122		u8 ctrl = 0;
123
124		dsi_device = intel_dsi->dsi_hosts[port]->device;
125
126		mipi_dsi_dcs_read(dsi_device, MIPI_DCS_GET_CONTROL_DISPLAY,
127				  &ctrl, sizeof(ctrl));
128
129		ctrl |= CONTROL_DISPLAY_BL;
130		ctrl |= CONTROL_DISPLAY_DD;
131		ctrl |= CONTROL_DISPLAY_BCTRL;
132
133		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_CONTROL_DISPLAY,
134				   &ctrl, sizeof(ctrl));
135	}
136
137	for_each_dsi_port(port, intel_dsi->dcs_cabc_ports) {
138		u8 cabc = POWER_SAVE_MEDIUM;
139
140		dsi_device = intel_dsi->dsi_hosts[port]->device;
141		mipi_dsi_dcs_write(dsi_device, MIPI_DCS_WRITE_POWER_SAVE,
142				   &cabc, sizeof(cabc));
143	}
144
145	dcs_set_backlight(connector, panel->backlight.level);
146}
147
148static int dcs_setup_backlight(struct intel_connector *connector,
149			       enum pipe unused)
150{
151	struct intel_panel *panel = &connector->panel;
152
153	panel->backlight.max = PANEL_PWM_MAX_VALUE;
154	panel->backlight.level = PANEL_PWM_MAX_VALUE;
155
156	return 0;
157}
158
159int intel_dsi_dcs_init_backlight_funcs(struct intel_connector *intel_connector)
160{
161	struct drm_device *dev = intel_connector->base.dev;
162	struct drm_i915_private *dev_priv = to_i915(dev);
163	struct intel_encoder *encoder = intel_connector->encoder;
164	struct intel_panel *panel = &intel_connector->panel;
165
166	if (dev_priv->vbt.backlight.type != INTEL_BACKLIGHT_DSI_DCS)
167		return -ENODEV;
168
169	if (WARN_ON(encoder->type != INTEL_OUTPUT_DSI))
170		return -EINVAL;
171
172	panel->backlight.setup = dcs_setup_backlight;
173	panel->backlight.enable = dcs_enable_backlight;
174	panel->backlight.disable = dcs_disable_backlight;
175	panel->backlight.set = dcs_set_backlight;
176	panel->backlight.get = dcs_get_backlight;
177
178	return 0;
179}