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