xref: /rk3399_rockchip-uboot/drivers/video/drm/rk618_lvds.c (revision 0594ce39a9e8c9a7c7c4890dbfacdb480903f892)
1117fdc89SWyon Bi // SPDX-License-Identifier: GPL-2.0+
2117fdc89SWyon Bi /*
3117fdc89SWyon Bi  * (C) Copyright 2008-2018 Fuzhou Rockchip Electronics Co., Ltd
4117fdc89SWyon Bi  */
5117fdc89SWyon Bi 
6117fdc89SWyon Bi #include <common.h>
7117fdc89SWyon Bi #include <dm.h>
8117fdc89SWyon Bi #include <dm/device-internal.h>
9117fdc89SWyon Bi #include <errno.h>
10117fdc89SWyon Bi #include <i2c.h>
11117fdc89SWyon Bi #include <video_bridge.h>
12117fdc89SWyon Bi #include <linux/media-bus-format.h>
13117fdc89SWyon Bi 
14117fdc89SWyon Bi #include "rockchip_display.h"
15117fdc89SWyon Bi #include "rockchip_bridge.h"
16117fdc89SWyon Bi #include "rockchip_panel.h"
17*0594ce39SZhang Yubing #include "rockchip_connector.h"
18117fdc89SWyon Bi 
19117fdc89SWyon Bi #include "rk618.h"
20117fdc89SWyon Bi 
21117fdc89SWyon Bi enum {
22117fdc89SWyon Bi 	LVDS_8BIT_MODE_FORMAT_1,
23117fdc89SWyon Bi 	LVDS_8BIT_MODE_FORMAT_2,
24117fdc89SWyon Bi 	LVDS_8BIT_MODE_FORMAT_3,
25117fdc89SWyon Bi 	LVDS_6BIT_MODE,
26117fdc89SWyon Bi };
27117fdc89SWyon Bi 
28117fdc89SWyon Bi struct rk618_lvds_priv {
29117fdc89SWyon Bi 	struct udevice *dev;
30117fdc89SWyon Bi 	struct rk618 *parent;
31117fdc89SWyon Bi 	bool dual_channel;
32117fdc89SWyon Bi };
33117fdc89SWyon Bi 
lvds_write(struct rk618_lvds_priv * priv,u16 reg,u32 val)34117fdc89SWyon Bi static int lvds_write(struct rk618_lvds_priv *priv, u16 reg, u32 val)
35117fdc89SWyon Bi {
36117fdc89SWyon Bi 	return rk618_i2c_write(priv->parent, reg, val);
37117fdc89SWyon Bi }
38117fdc89SWyon Bi 
rk618_lvds_bridge_enable(struct rockchip_bridge * bridge)39117fdc89SWyon Bi static void rk618_lvds_bridge_enable(struct rockchip_bridge *bridge)
40117fdc89SWyon Bi {
41117fdc89SWyon Bi 	struct rk618_lvds_priv *priv = dev_get_priv(bridge->dev);
42*0594ce39SZhang Yubing 	struct rockchip_panel *panel = bridge->conn->panel;
43117fdc89SWyon Bi 	u32 value, format;
44117fdc89SWyon Bi 
45117fdc89SWyon Bi 	rk618_frc_dclk_invert(priv->parent);
46117fdc89SWyon Bi 
47117fdc89SWyon Bi 	switch (panel->bus_format) {
48cf0aae68SWyon Bi 	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:	/* jeida-18 */
49117fdc89SWyon Bi 		format = LVDS_6BIT_MODE;
50117fdc89SWyon Bi 		break;
51117fdc89SWyon Bi 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:	/* jeida-24 */
52117fdc89SWyon Bi 		format = LVDS_8BIT_MODE_FORMAT_2;
53117fdc89SWyon Bi 		break;
54cf0aae68SWyon Bi 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:	/* vesa-18 */
55117fdc89SWyon Bi 		format = LVDS_8BIT_MODE_FORMAT_3;
56117fdc89SWyon Bi 		break;
57cf0aae68SWyon Bi 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:	/* vesa-24 */
58cf0aae68SWyon Bi 	default:
59cf0aae68SWyon Bi 		format = LVDS_8BIT_MODE_FORMAT_1;
60cf0aae68SWyon Bi 		break;
61117fdc89SWyon Bi 	}
62117fdc89SWyon Bi 
63117fdc89SWyon Bi 	value = LVDS_CON_CHA0TTL_DISABLE | LVDS_CON_CHA1TTL_DISABLE |
64117fdc89SWyon Bi 		LVDS_CON_CHA0_POWER_UP | LVDS_CON_CBG_POWER_UP |
65117fdc89SWyon Bi 		LVDS_CON_PLL_POWER_UP | LVDS_CON_SELECT(format);
66117fdc89SWyon Bi 
67117fdc89SWyon Bi 	if (priv->dual_channel)
68117fdc89SWyon Bi 		value |= LVDS_CON_CHA1_POWER_UP | LVDS_DCLK_INV |
69117fdc89SWyon Bi 			 LVDS_CON_CHASEL_DOUBLE_CHANNEL;
70117fdc89SWyon Bi 	else
71117fdc89SWyon Bi 		value |= LVDS_CON_CHA1_POWER_DOWN |
72117fdc89SWyon Bi 			 LVDS_CON_CHASEL_SINGLE_CHANNEL;
73117fdc89SWyon Bi 
74117fdc89SWyon Bi 	lvds_write(priv, RK618_LVDS_CON, value);
75117fdc89SWyon Bi }
76117fdc89SWyon Bi 
rk618_lvds_bridge_disable(struct rockchip_bridge * bridge)77117fdc89SWyon Bi static void rk618_lvds_bridge_disable(struct rockchip_bridge *bridge)
78117fdc89SWyon Bi {
79117fdc89SWyon Bi 	struct rk618_lvds_priv *priv = dev_get_priv(bridge->dev);
80117fdc89SWyon Bi 
81117fdc89SWyon Bi 	lvds_write(priv, RK618_LVDS_CON,
82117fdc89SWyon Bi 		   LVDS_CON_CHA0_POWER_DOWN | LVDS_CON_CHA1_POWER_DOWN |
83117fdc89SWyon Bi 		   LVDS_CON_CBG_POWER_DOWN | LVDS_CON_PLL_POWER_DOWN);
84117fdc89SWyon Bi }
85117fdc89SWyon Bi 
86117fdc89SWyon Bi static const struct rockchip_bridge_funcs rk618_lvds_bridge_funcs = {
87117fdc89SWyon Bi 	.enable = rk618_lvds_bridge_enable,
88117fdc89SWyon Bi 	.disable = rk618_lvds_bridge_disable,
89117fdc89SWyon Bi };
90117fdc89SWyon Bi 
rk618_lvds_probe(struct udevice * dev)91117fdc89SWyon Bi static int rk618_lvds_probe(struct udevice *dev)
92117fdc89SWyon Bi {
93117fdc89SWyon Bi 	struct rk618_lvds_priv *priv = dev_get_priv(dev);
94117fdc89SWyon Bi 	struct rockchip_bridge *bridge =
95117fdc89SWyon Bi 		(struct rockchip_bridge *)dev_get_driver_data(dev);
96117fdc89SWyon Bi 	int ret;
97117fdc89SWyon Bi 
98117fdc89SWyon Bi 	priv->dev = dev;
99117fdc89SWyon Bi 	priv->parent = dev_get_priv(dev->parent);
100117fdc89SWyon Bi 	priv->dual_channel = dev_read_bool(dev, "dual-channel");
101117fdc89SWyon Bi 
102117fdc89SWyon Bi 	ret = device_probe(dev->parent);
103117fdc89SWyon Bi 	if (ret)
104117fdc89SWyon Bi 		return ret;
105117fdc89SWyon Bi 
106117fdc89SWyon Bi 	bridge->dev = dev;
107117fdc89SWyon Bi 
108117fdc89SWyon Bi 	return 0;
109117fdc89SWyon Bi }
110117fdc89SWyon Bi 
111117fdc89SWyon Bi static struct rockchip_bridge rk618_lvds_driver_data = {
112117fdc89SWyon Bi 	.funcs = &rk618_lvds_bridge_funcs,
113117fdc89SWyon Bi };
114117fdc89SWyon Bi 
115117fdc89SWyon Bi static const struct udevice_id rk618_lvds_ids[] = {
116117fdc89SWyon Bi 	{
117117fdc89SWyon Bi 		.compatible = "rockchip,rk618-lvds",
118117fdc89SWyon Bi 		.data = (ulong)&rk618_lvds_driver_data,
119117fdc89SWyon Bi 	},
120117fdc89SWyon Bi 	{ }
121117fdc89SWyon Bi };
122117fdc89SWyon Bi 
123117fdc89SWyon Bi U_BOOT_DRIVER(rk618_lvds) = {
124117fdc89SWyon Bi 	.name = "rk618_lvds",
125117fdc89SWyon Bi 	.id = UCLASS_VIDEO_BRIDGE,
126117fdc89SWyon Bi 	.of_match = rk618_lvds_ids,
127117fdc89SWyon Bi 	.probe = rk618_lvds_probe,
128117fdc89SWyon Bi 	.priv_auto_alloc_size = sizeof(struct rk618_lvds_priv),
129117fdc89SWyon Bi };
130