xref: /OK3568_Linux_fs/u-boot/drivers/video/drm/rk618_lvds.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) Copyright 2008-2018 Fuzhou Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <dm.h>
8*4882a593Smuzhiyun #include <dm/device-internal.h>
9*4882a593Smuzhiyun #include <errno.h>
10*4882a593Smuzhiyun #include <i2c.h>
11*4882a593Smuzhiyun #include <video_bridge.h>
12*4882a593Smuzhiyun #include <linux/media-bus-format.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include "rockchip_display.h"
15*4882a593Smuzhiyun #include "rockchip_bridge.h"
16*4882a593Smuzhiyun #include "rockchip_panel.h"
17*4882a593Smuzhiyun #include "rockchip_connector.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #include "rk618.h"
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun enum {
22*4882a593Smuzhiyun 	LVDS_8BIT_MODE_FORMAT_1,
23*4882a593Smuzhiyun 	LVDS_8BIT_MODE_FORMAT_2,
24*4882a593Smuzhiyun 	LVDS_8BIT_MODE_FORMAT_3,
25*4882a593Smuzhiyun 	LVDS_6BIT_MODE,
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun struct rk618_lvds_priv {
29*4882a593Smuzhiyun 	struct udevice *dev;
30*4882a593Smuzhiyun 	struct rk618 *parent;
31*4882a593Smuzhiyun 	bool dual_channel;
32*4882a593Smuzhiyun };
33*4882a593Smuzhiyun 
lvds_write(struct rk618_lvds_priv * priv,u16 reg,u32 val)34*4882a593Smuzhiyun static int lvds_write(struct rk618_lvds_priv *priv, u16 reg, u32 val)
35*4882a593Smuzhiyun {
36*4882a593Smuzhiyun 	return rk618_i2c_write(priv->parent, reg, val);
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
rk618_lvds_bridge_enable(struct rockchip_bridge * bridge)39*4882a593Smuzhiyun static void rk618_lvds_bridge_enable(struct rockchip_bridge *bridge)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	struct rk618_lvds_priv *priv = dev_get_priv(bridge->dev);
42*4882a593Smuzhiyun 	struct rockchip_panel *panel = bridge->conn->panel;
43*4882a593Smuzhiyun 	u32 value, format;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	rk618_frc_dclk_invert(priv->parent);
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	switch (panel->bus_format) {
48*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X7X3_JEIDA:	/* jeida-18 */
49*4882a593Smuzhiyun 		format = LVDS_6BIT_MODE;
50*4882a593Smuzhiyun 		break;
51*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:	/* jeida-24 */
52*4882a593Smuzhiyun 		format = LVDS_8BIT_MODE_FORMAT_2;
53*4882a593Smuzhiyun 		break;
54*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:	/* vesa-18 */
55*4882a593Smuzhiyun 		format = LVDS_8BIT_MODE_FORMAT_3;
56*4882a593Smuzhiyun 		break;
57*4882a593Smuzhiyun 	case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:	/* vesa-24 */
58*4882a593Smuzhiyun 	default:
59*4882a593Smuzhiyun 		format = LVDS_8BIT_MODE_FORMAT_1;
60*4882a593Smuzhiyun 		break;
61*4882a593Smuzhiyun 	}
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	value = LVDS_CON_CHA0TTL_DISABLE | LVDS_CON_CHA1TTL_DISABLE |
64*4882a593Smuzhiyun 		LVDS_CON_CHA0_POWER_UP | LVDS_CON_CBG_POWER_UP |
65*4882a593Smuzhiyun 		LVDS_CON_PLL_POWER_UP | LVDS_CON_SELECT(format);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	if (priv->dual_channel)
68*4882a593Smuzhiyun 		value |= LVDS_CON_CHA1_POWER_UP | LVDS_DCLK_INV |
69*4882a593Smuzhiyun 			 LVDS_CON_CHASEL_DOUBLE_CHANNEL;
70*4882a593Smuzhiyun 	else
71*4882a593Smuzhiyun 		value |= LVDS_CON_CHA1_POWER_DOWN |
72*4882a593Smuzhiyun 			 LVDS_CON_CHASEL_SINGLE_CHANNEL;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 	lvds_write(priv, RK618_LVDS_CON, value);
75*4882a593Smuzhiyun }
76*4882a593Smuzhiyun 
rk618_lvds_bridge_disable(struct rockchip_bridge * bridge)77*4882a593Smuzhiyun static void rk618_lvds_bridge_disable(struct rockchip_bridge *bridge)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun 	struct rk618_lvds_priv *priv = dev_get_priv(bridge->dev);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	lvds_write(priv, RK618_LVDS_CON,
82*4882a593Smuzhiyun 		   LVDS_CON_CHA0_POWER_DOWN | LVDS_CON_CHA1_POWER_DOWN |
83*4882a593Smuzhiyun 		   LVDS_CON_CBG_POWER_DOWN | LVDS_CON_PLL_POWER_DOWN);
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static const struct rockchip_bridge_funcs rk618_lvds_bridge_funcs = {
87*4882a593Smuzhiyun 	.enable = rk618_lvds_bridge_enable,
88*4882a593Smuzhiyun 	.disable = rk618_lvds_bridge_disable,
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun 
rk618_lvds_probe(struct udevice * dev)91*4882a593Smuzhiyun static int rk618_lvds_probe(struct udevice *dev)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun 	struct rk618_lvds_priv *priv = dev_get_priv(dev);
94*4882a593Smuzhiyun 	struct rockchip_bridge *bridge =
95*4882a593Smuzhiyun 		(struct rockchip_bridge *)dev_get_driver_data(dev);
96*4882a593Smuzhiyun 	int ret;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	priv->dev = dev;
99*4882a593Smuzhiyun 	priv->parent = dev_get_priv(dev->parent);
100*4882a593Smuzhiyun 	priv->dual_channel = dev_read_bool(dev, "dual-channel");
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	ret = device_probe(dev->parent);
103*4882a593Smuzhiyun 	if (ret)
104*4882a593Smuzhiyun 		return ret;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	bridge->dev = dev;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	return 0;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun static struct rockchip_bridge rk618_lvds_driver_data = {
112*4882a593Smuzhiyun 	.funcs = &rk618_lvds_bridge_funcs,
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun static const struct udevice_id rk618_lvds_ids[] = {
116*4882a593Smuzhiyun 	{
117*4882a593Smuzhiyun 		.compatible = "rockchip,rk618-lvds",
118*4882a593Smuzhiyun 		.data = (ulong)&rk618_lvds_driver_data,
119*4882a593Smuzhiyun 	},
120*4882a593Smuzhiyun 	{ }
121*4882a593Smuzhiyun };
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun U_BOOT_DRIVER(rk618_lvds) = {
124*4882a593Smuzhiyun 	.name = "rk618_lvds",
125*4882a593Smuzhiyun 	.id = UCLASS_VIDEO_BRIDGE,
126*4882a593Smuzhiyun 	.of_match = rk618_lvds_ids,
127*4882a593Smuzhiyun 	.probe = rk618_lvds_probe,
128*4882a593Smuzhiyun 	.priv_auto_alloc_size = sizeof(struct rk618_lvds_priv),
129*4882a593Smuzhiyun };
130