blob: 1b8aa12b9e8885c39fbed0e10f024be5ce849b1b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass7cf17572015-07-02 18:16:08 -06002/*
3 * Copyright (C) 2015 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
Simon Glass7cf17572015-07-02 18:16:08 -06005 */
6
Patrick Delaunay81313352021-04-27 11:02:19 +02007#define LOG_CATEGORY UCLASS_VIDEO_BRIDGE
8
Simon Glass7cf17572015-07-02 18:16:08 -06009#include <dm.h>
10#include <errno.h>
Vasily Khoruzhick82e9a5a2017-09-20 23:29:07 -070011#include <edid.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glass7cf17572015-07-02 18:16:08 -060013#include <video_bridge.h>
Simon Glassdbd79542020-05-10 11:40:11 -060014#include <linux/delay.h>
Simon Glass7cf17572015-07-02 18:16:08 -060015
16int video_bridge_set_backlight(struct udevice *dev, int percent)
17{
18 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
19
20 if (!ops->set_backlight)
21 return -ENOSYS;
22
23 return ops->set_backlight(dev, percent);
24}
25
26int video_bridge_attach(struct udevice *dev)
27{
28 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
29
30 if (!ops->attach)
31 return -ENOSYS;
32
33 return ops->attach(dev);
34}
35
Svyatoslav Ryhelff9d0922025-02-14 10:57:05 +020036int video_bridge_get_display_timing(struct udevice *dev,
37 struct display_timing *timings)
38{
39 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
40
41 if (!ops->get_display_timing)
42 return -ENOSYS;
43
44 return ops->get_display_timing(dev, timings);
45}
46
Simon Glass7cf17572015-07-02 18:16:08 -060047int video_bridge_check_attached(struct udevice *dev)
48{
49 struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
50 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
51 int ret;
52
53 if (!ops->check_attached) {
54 ret = dm_gpio_get_value(&uc_priv->hotplug);
55
56 return ret > 0 ? 0 : ret == 0 ? -ENOTCONN : ret;
57 }
58
59 return ops->check_attached(dev);
60}
61
Vasily Khoruzhick82e9a5a2017-09-20 23:29:07 -070062int video_bridge_read_edid(struct udevice *dev, u8 *buf, int buf_size)
63{
64 struct video_bridge_ops *ops = video_bridge_get_ops(dev);
65
66 if (!ops || !ops->read_edid)
67 return -ENOSYS;
68 return ops->read_edid(dev, buf, buf_size);
69}
70
Simon Glass7cf17572015-07-02 18:16:08 -060071static int video_bridge_pre_probe(struct udevice *dev)
72{
73 struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
74 int ret;
75
76 debug("%s\n", __func__);
77 ret = gpio_request_by_name(dev, "sleep-gpios", 0,
78 &uc_priv->sleep, GPIOD_IS_OUT);
79 if (ret) {
80 debug("%s: Could not decode sleep-gpios (%d)\n", __func__, ret);
Simon Glass661d5de2016-01-21 19:44:53 -070081 if (ret != -ENOENT)
82 return ret;
Simon Glass7cf17572015-07-02 18:16:08 -060083 }
Simon Glassbe72e332015-08-03 08:19:20 -060084 /*
85 * Drop this for now as we do not have driver model pinctrl support
86 *
87 * ret = dm_gpio_set_pull(&uc_priv->sleep, GPIO_PULL_NONE);
88 * if (ret) {
89 * debug("%s: Could not set sleep pull value\n", __func__);
90 * return ret;
91 * }
92 */
Simon Glass7cf17572015-07-02 18:16:08 -060093 ret = gpio_request_by_name(dev, "reset-gpios", 0, &uc_priv->reset,
94 GPIOD_IS_OUT);
95 if (ret) {
96 debug("%s: Could not decode reset-gpios (%d)\n", __func__, ret);
Simon Glass661d5de2016-01-21 19:44:53 -070097 if (ret != -ENOENT)
98 return ret;
Simon Glass7cf17572015-07-02 18:16:08 -060099 }
Simon Glassbe72e332015-08-03 08:19:20 -0600100 /*
101 * Drop this for now as we do not have driver model pinctrl support
102 *
103 * ret = dm_gpio_set_pull(&uc_priv->reset, GPIO_PULL_NONE);
104 * if (ret) {
105 * debug("%s: Could not set reset pull value\n", __func__);
106 * return ret;
107 * }
108 */
Simon Glass7cf17572015-07-02 18:16:08 -0600109 ret = gpio_request_by_name(dev, "hotplug-gpios", 0, &uc_priv->hotplug,
110 GPIOD_IS_IN);
Simon Glass661d5de2016-01-21 19:44:53 -0700111 if (ret) {
Simon Glass7cf17572015-07-02 18:16:08 -0600112 debug("%s: Could not decode hotplug (%d)\n", __func__, ret);
Simon Glass661d5de2016-01-21 19:44:53 -0700113 if (ret != -ENOENT)
114 return ret;
Simon Glass7cf17572015-07-02 18:16:08 -0600115 }
116
117 return 0;
118}
119
120int video_bridge_set_active(struct udevice *dev, bool active)
121{
122 struct video_bridge_priv *uc_priv = dev_get_uclass_priv(dev);
Vasily Khoruzhicke0b22602018-11-05 20:24:29 -0800123 int ret = 0;
Simon Glass7cf17572015-07-02 18:16:08 -0600124
125 debug("%s: %d\n", __func__, active);
Vasily Khoruzhicke0b22602018-11-05 20:24:29 -0800126 if (uc_priv->sleep.dev) {
127 ret = dm_gpio_set_value(&uc_priv->sleep, !active);
128 if (ret)
129 return ret;
130 }
131
132 if (!active)
133 return 0;
134
135 if (uc_priv->reset.dev) {
Simon Glass7cf17572015-07-02 18:16:08 -0600136 ret = dm_gpio_set_value(&uc_priv->reset, true);
137 if (ret)
138 return ret;
139 udelay(10);
140 ret = dm_gpio_set_value(&uc_priv->reset, false);
141 }
142
143 return ret;
144}
145
146UCLASS_DRIVER(video_bridge) = {
147 .id = UCLASS_VIDEO_BRIDGE,
148 .name = "video_bridge",
Simon Glass8a2b47f2020-12-03 16:55:17 -0700149 .per_device_auto = sizeof(struct video_bridge_priv),
Simon Glass7cf17572015-07-02 18:16:08 -0600150 .pre_probe = video_bridge_pre_probe,
151};