treewide: remove redundant IS_ERR() before error code check
[linux/fpc-iii.git] / drivers / gpu / drm / msm / hdmi / hdmi_bridge.c
blobba81338a9bf84be221bb08154cb985e0737ed1b9
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Copyright (C) 2013 Red Hat
4 * Author: Rob Clark <robdclark@gmail.com>
5 */
7 #include <linux/delay.h>
9 #include "hdmi.h"
11 struct hdmi_bridge {
12 struct drm_bridge base;
13 struct hdmi *hdmi;
15 #define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
17 void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
21 static void msm_hdmi_power_on(struct drm_bridge *bridge)
23 struct drm_device *dev = bridge->dev;
24 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
25 struct hdmi *hdmi = hdmi_bridge->hdmi;
26 const struct hdmi_platform_config *config = hdmi->config;
27 int i, ret;
29 pm_runtime_get_sync(&hdmi->pdev->dev);
31 for (i = 0; i < config->pwr_reg_cnt; i++) {
32 ret = regulator_enable(hdmi->pwr_regs[i]);
33 if (ret) {
34 DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %s (%d)\n",
35 config->pwr_reg_names[i], ret);
39 if (config->pwr_clk_cnt > 0) {
40 DBG("pixclock: %lu", hdmi->pixclock);
41 ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock);
42 if (ret) {
43 DRM_DEV_ERROR(dev->dev, "failed to set pixel clk: %s (%d)\n",
44 config->pwr_clk_names[0], ret);
48 for (i = 0; i < config->pwr_clk_cnt; i++) {
49 ret = clk_prepare_enable(hdmi->pwr_clks[i]);
50 if (ret) {
51 DRM_DEV_ERROR(dev->dev, "failed to enable pwr clk: %s (%d)\n",
52 config->pwr_clk_names[i], ret);
57 static void power_off(struct drm_bridge *bridge)
59 struct drm_device *dev = bridge->dev;
60 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
61 struct hdmi *hdmi = hdmi_bridge->hdmi;
62 const struct hdmi_platform_config *config = hdmi->config;
63 int i, ret;
65 /* TODO do we need to wait for final vblank somewhere before
66 * cutting the clocks?
68 mdelay(16 + 4);
70 for (i = 0; i < config->pwr_clk_cnt; i++)
71 clk_disable_unprepare(hdmi->pwr_clks[i]);
73 for (i = 0; i < config->pwr_reg_cnt; i++) {
74 ret = regulator_disable(hdmi->pwr_regs[i]);
75 if (ret) {
76 DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %s (%d)\n",
77 config->pwr_reg_names[i], ret);
81 pm_runtime_put_autosuspend(&hdmi->pdev->dev);
84 #define AVI_IFRAME_LINE_NUMBER 1
86 static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi)
88 struct drm_crtc *crtc = hdmi->encoder->crtc;
89 const struct drm_display_mode *mode = &crtc->state->adjusted_mode;
90 union hdmi_infoframe frame;
91 u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
92 u32 val;
93 int len;
95 drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
96 hdmi->connector, mode);
98 len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer));
99 if (len < 0) {
100 DRM_DEV_ERROR(&hdmi->pdev->dev,
101 "failed to configure avi infoframe\n");
102 return;
106 * the AVI_INFOx registers don't map exactly to how the AVI infoframes
107 * are packed according to the spec. The checksum from the header is
108 * written to the LSB byte of AVI_INFO0 and the version is written to
109 * the third byte from the LSB of AVI_INFO3
111 hdmi_write(hdmi, REG_HDMI_AVI_INFO(0),
112 buffer[3] |
113 buffer[4] << 8 |
114 buffer[5] << 16 |
115 buffer[6] << 24);
117 hdmi_write(hdmi, REG_HDMI_AVI_INFO(1),
118 buffer[7] |
119 buffer[8] << 8 |
120 buffer[9] << 16 |
121 buffer[10] << 24);
123 hdmi_write(hdmi, REG_HDMI_AVI_INFO(2),
124 buffer[11] |
125 buffer[12] << 8 |
126 buffer[13] << 16 |
127 buffer[14] << 24);
129 hdmi_write(hdmi, REG_HDMI_AVI_INFO(3),
130 buffer[15] |
131 buffer[16] << 8 |
132 buffer[1] << 24);
134 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0,
135 HDMI_INFOFRAME_CTRL0_AVI_SEND |
136 HDMI_INFOFRAME_CTRL0_AVI_CONT);
138 val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1);
139 val &= ~HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE__MASK;
140 val |= HDMI_INFOFRAME_CTRL1_AVI_INFO_LINE(AVI_IFRAME_LINE_NUMBER);
141 hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val);
144 static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
146 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
147 struct hdmi *hdmi = hdmi_bridge->hdmi;
148 struct hdmi_phy *phy = hdmi->phy;
150 DBG("power up");
152 if (!hdmi->power_on) {
153 msm_hdmi_phy_resource_enable(phy);
154 msm_hdmi_power_on(bridge);
155 hdmi->power_on = true;
156 if (hdmi->hdmi_mode) {
157 msm_hdmi_config_avi_infoframe(hdmi);
158 msm_hdmi_audio_update(hdmi);
162 msm_hdmi_phy_powerup(phy, hdmi->pixclock);
164 msm_hdmi_set_mode(hdmi, true);
166 if (hdmi->hdcp_ctrl)
167 msm_hdmi_hdcp_on(hdmi->hdcp_ctrl);
170 static void msm_hdmi_bridge_enable(struct drm_bridge *bridge)
174 static void msm_hdmi_bridge_disable(struct drm_bridge *bridge)
178 static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge)
180 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
181 struct hdmi *hdmi = hdmi_bridge->hdmi;
182 struct hdmi_phy *phy = hdmi->phy;
184 if (hdmi->hdcp_ctrl)
185 msm_hdmi_hdcp_off(hdmi->hdcp_ctrl);
187 DBG("power down");
188 msm_hdmi_set_mode(hdmi, false);
190 msm_hdmi_phy_powerdown(phy);
192 if (hdmi->power_on) {
193 power_off(bridge);
194 hdmi->power_on = false;
195 if (hdmi->hdmi_mode)
196 msm_hdmi_audio_update(hdmi);
197 msm_hdmi_phy_resource_disable(phy);
201 static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
202 const struct drm_display_mode *mode,
203 const struct drm_display_mode *adjusted_mode)
205 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
206 struct hdmi *hdmi = hdmi_bridge->hdmi;
207 int hstart, hend, vstart, vend;
208 uint32_t frame_ctrl;
210 mode = adjusted_mode;
212 hdmi->pixclock = mode->clock * 1000;
214 hstart = mode->htotal - mode->hsync_start;
215 hend = mode->htotal - mode->hsync_start + mode->hdisplay;
217 vstart = mode->vtotal - mode->vsync_start - 1;
218 vend = mode->vtotal - mode->vsync_start + mode->vdisplay - 1;
220 DBG("htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d",
221 mode->htotal, mode->vtotal, hstart, hend, vstart, vend);
223 hdmi_write(hdmi, REG_HDMI_TOTAL,
224 HDMI_TOTAL_H_TOTAL(mode->htotal - 1) |
225 HDMI_TOTAL_V_TOTAL(mode->vtotal - 1));
227 hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC,
228 HDMI_ACTIVE_HSYNC_START(hstart) |
229 HDMI_ACTIVE_HSYNC_END(hend));
230 hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC,
231 HDMI_ACTIVE_VSYNC_START(vstart) |
232 HDMI_ACTIVE_VSYNC_END(vend));
234 if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
235 hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
236 HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal));
237 hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
238 HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) |
239 HDMI_VSYNC_ACTIVE_F2_END(vend + 1));
240 } else {
241 hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
242 HDMI_VSYNC_TOTAL_F2_V_TOTAL(0));
243 hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
244 HDMI_VSYNC_ACTIVE_F2_START(0) |
245 HDMI_VSYNC_ACTIVE_F2_END(0));
248 frame_ctrl = 0;
249 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
250 frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW;
251 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
252 frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW;
253 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
254 frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN;
255 DBG("frame_ctrl=%08x", frame_ctrl);
256 hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);
258 if (hdmi->hdmi_mode)
259 msm_hdmi_audio_update(hdmi);
262 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
263 .pre_enable = msm_hdmi_bridge_pre_enable,
264 .enable = msm_hdmi_bridge_enable,
265 .disable = msm_hdmi_bridge_disable,
266 .post_disable = msm_hdmi_bridge_post_disable,
267 .mode_set = msm_hdmi_bridge_mode_set,
271 /* initialize bridge */
272 struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
274 struct drm_bridge *bridge = NULL;
275 struct hdmi_bridge *hdmi_bridge;
276 int ret;
278 hdmi_bridge = devm_kzalloc(hdmi->dev->dev,
279 sizeof(*hdmi_bridge), GFP_KERNEL);
280 if (!hdmi_bridge) {
281 ret = -ENOMEM;
282 goto fail;
285 hdmi_bridge->hdmi = hdmi;
287 bridge = &hdmi_bridge->base;
288 bridge->funcs = &msm_hdmi_bridge_funcs;
290 ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
291 if (ret)
292 goto fail;
294 return bridge;
296 fail:
297 if (bridge)
298 msm_hdmi_bridge_destroy(bridge);
300 return ERR_PTR(ret);