forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-13 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e
kernel/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
....@@ -1,30 +1,20 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2013 Red Hat
34 * Author: Rob Clark <robdclark@gmail.com>
4
- *
5
- * This program is free software; you can redistribute it and/or modify it
6
- * under the terms of the GNU General Public License version 2 as published by
7
- * the Free Software Foundation.
8
- *
9
- * This program is distributed in the hope that it will be useful, but WITHOUT
10
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12
- * more details.
13
- *
14
- * You should have received a copy of the GNU General Public License along with
15
- * this program. If not, see <http://www.gnu.org/licenses/>.
165 */
176
18
-#include "hdmi.h"
7
+#include <linux/delay.h>
8
+#include <drm/drm_bridge_connector.h>
199
20
-struct hdmi_bridge {
21
- struct drm_bridge base;
22
- struct hdmi *hdmi;
23
-};
24
-#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)
10
+#include "msm_kms.h"
11
+#include "hdmi.h"
2512
2613 void msm_hdmi_bridge_destroy(struct drm_bridge *bridge)
2714 {
15
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
16
+
17
+ msm_hdmi_hpd_disable(hdmi_bridge);
2818 }
2919
3020 static void msm_hdmi_power_on(struct drm_bridge *bridge)
....@@ -40,7 +30,7 @@
4030 for (i = 0; i < config->pwr_reg_cnt; i++) {
4131 ret = regulator_enable(hdmi->pwr_regs[i]);
4232 if (ret) {
43
- dev_err(dev->dev, "failed to enable pwr regulator: %s (%d)\n",
33
+ DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %s (%d)\n",
4434 config->pwr_reg_names[i], ret);
4535 }
4636 }
....@@ -49,7 +39,7 @@
4939 DBG("pixclock: %lu", hdmi->pixclock);
5040 ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock);
5141 if (ret) {
52
- dev_err(dev->dev, "failed to set pixel clk: %s (%d)\n",
42
+ DRM_DEV_ERROR(dev->dev, "failed to set pixel clk: %s (%d)\n",
5343 config->pwr_clk_names[0], ret);
5444 }
5545 }
....@@ -57,7 +47,7 @@
5747 for (i = 0; i < config->pwr_clk_cnt; i++) {
5848 ret = clk_prepare_enable(hdmi->pwr_clks[i]);
5949 if (ret) {
60
- dev_err(dev->dev, "failed to enable pwr clk: %s (%d)\n",
50
+ DRM_DEV_ERROR(dev->dev, "failed to enable pwr clk: %s (%d)\n",
6151 config->pwr_clk_names[i], ret);
6252 }
6353 }
....@@ -82,7 +72,7 @@
8272 for (i = 0; i < config->pwr_reg_cnt; i++) {
8373 ret = regulator_disable(hdmi->pwr_regs[i]);
8474 if (ret) {
85
- dev_err(dev->dev, "failed to disable pwr regulator: %s (%d)\n",
75
+ DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %s (%d)\n",
8676 config->pwr_reg_names[i], ret);
8777 }
8878 }
....@@ -101,11 +91,12 @@
10191 u32 val;
10292 int len;
10393
104
- drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
94
+ drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
95
+ hdmi->connector, mode);
10596
10697 len = hdmi_infoframe_pack(&frame, buffer, sizeof(buffer));
10798 if (len < 0) {
108
- dev_err(&hdmi->pdev->dev,
99
+ DRM_DEV_ERROR(&hdmi->pdev->dev,
109100 "failed to configure avi infoframe\n");
110101 return;
111102 }
....@@ -207,8 +198,8 @@
207198 }
208199
209200 static void msm_hdmi_bridge_mode_set(struct drm_bridge *bridge,
210
- struct drm_display_mode *mode,
211
- struct drm_display_mode *adjusted_mode)
201
+ const struct drm_display_mode *mode,
202
+ const struct drm_display_mode *adjusted_mode)
212203 {
213204 struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
214205 struct hdmi *hdmi = hdmi_bridge->hdmi;
....@@ -267,14 +258,76 @@
267258 msm_hdmi_audio_update(hdmi);
268259 }
269260
261
+static struct edid *msm_hdmi_bridge_get_edid(struct drm_bridge *bridge,
262
+ struct drm_connector *connector)
263
+{
264
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
265
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
266
+ struct edid *edid;
267
+ uint32_t hdmi_ctrl;
268
+
269
+ hdmi_ctrl = hdmi_read(hdmi, REG_HDMI_CTRL);
270
+ hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl | HDMI_CTRL_ENABLE);
271
+
272
+ edid = drm_get_edid(connector, hdmi->i2c);
273
+
274
+ hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl);
275
+
276
+ hdmi->hdmi_mode = drm_detect_hdmi_monitor(edid);
277
+
278
+ return edid;
279
+}
280
+
281
+static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
282
+ const struct drm_display_info *info,
283
+ const struct drm_display_mode *mode)
284
+{
285
+ struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
286
+ struct hdmi *hdmi = hdmi_bridge->hdmi;
287
+ const struct hdmi_platform_config *config = hdmi->config;
288
+ struct msm_drm_private *priv = bridge->dev->dev_private;
289
+ struct msm_kms *kms = priv->kms;
290
+ long actual, requested;
291
+
292
+ requested = 1000 * mode->clock;
293
+ actual = kms->funcs->round_pixclk(kms,
294
+ requested, hdmi_bridge->hdmi->encoder);
295
+
296
+ /* for mdp5/apq8074, we manage our own pixel clk (as opposed to
297
+ * mdp4/dtv stuff where pixel clk is assigned to mdp/encoder
298
+ * instead):
299
+ */
300
+ if (config->pwr_clk_cnt > 0)
301
+ actual = clk_round_rate(hdmi->pwr_clks[0], actual);
302
+
303
+ DBG("requested=%ld, actual=%ld", requested, actual);
304
+
305
+ if (actual != requested)
306
+ return MODE_CLOCK_RANGE;
307
+
308
+ return 0;
309
+}
310
+
270311 static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = {
271312 .pre_enable = msm_hdmi_bridge_pre_enable,
272313 .enable = msm_hdmi_bridge_enable,
273314 .disable = msm_hdmi_bridge_disable,
274315 .post_disable = msm_hdmi_bridge_post_disable,
275316 .mode_set = msm_hdmi_bridge_mode_set,
317
+ .mode_valid = msm_hdmi_bridge_mode_valid,
318
+ .get_edid = msm_hdmi_bridge_get_edid,
319
+ .detect = msm_hdmi_bridge_detect,
276320 };
277321
322
+static void
323
+msm_hdmi_hotplug_work(struct work_struct *work)
324
+{
325
+ struct hdmi_bridge *hdmi_bridge =
326
+ container_of(work, struct hdmi_bridge, hpd_work);
327
+ struct drm_bridge *bridge = &hdmi_bridge->base;
328
+
329
+ drm_bridge_hpd_notify(bridge, drm_bridge_detect(bridge));
330
+}
278331
279332 /* initialize bridge */
280333 struct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi)
....@@ -291,11 +344,17 @@
291344 }
292345
293346 hdmi_bridge->hdmi = hdmi;
347
+ INIT_WORK(&hdmi_bridge->hpd_work, msm_hdmi_hotplug_work);
294348
295349 bridge = &hdmi_bridge->base;
296350 bridge->funcs = &msm_hdmi_bridge_funcs;
351
+ bridge->ddc = hdmi->i2c;
352
+ bridge->type = DRM_MODE_CONNECTOR_HDMIA;
353
+ bridge->ops = DRM_BRIDGE_OP_HPD |
354
+ DRM_BRIDGE_OP_DETECT |
355
+ DRM_BRIDGE_OP_EDID;
297356
298
- ret = drm_bridge_attach(hdmi->encoder, bridge, NULL);
357
+ ret = drm_bridge_attach(hdmi->encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
299358 if (ret)
300359 goto fail;
301360