1 /* 2 * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <errno.h> 9 #include <syscon.h> 10 #include <regmap.h> 11 #include <dm/device.h> 12 #include <dm/read.h> 13 14 #include "rockchip_display.h" 15 #include "rockchip_crtc.h" 16 #include "rockchip_connector.h" 17 18 #define PX30_GRF_PD_VO_CON1 0x0438 19 #define PX30_LCDC_DCLK_INV(v) HIWORD_UPDATE(v, 4, 4) 20 #define PX30_RGB_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3) 21 #define PX30_RGB_VOP_SEL(v) HIWORD_UPDATE(v, 2, 2) 22 23 struct rockchip_rgb_priv { 24 struct regmap *grf; 25 }; 26 27 static int rockchip_rgb_prepare(struct display_state *state) 28 { 29 struct connector_state *conn_state = &state->conn_state; 30 struct rockchip_rgb_priv *priv = dev_get_priv(conn_state->dev); 31 struct crtc_state *crtc_state = &state->crtc_state; 32 int pipe = crtc_state->crtc_id; 33 34 if (!IS_ERR_OR_NULL(priv->grf)) { 35 regmap_write(priv->grf, PX30_GRF_PD_VO_CON1, 36 PX30_RGB_VOP_SEL(pipe)); 37 regmap_write(priv->grf, PX30_GRF_PD_VO_CON1, 38 PX30_RGB_SYNC_BYPASS(1)); 39 } 40 41 return 0; 42 } 43 44 static int rockchip_rgb_unprepare(struct display_state *state) 45 { 46 return 0; 47 } 48 49 static int to_output_mode(const char *s) 50 { 51 const struct { 52 const char *name; 53 int format; 54 } formats[] = { 55 { "p888", ROCKCHIP_OUT_MODE_P888 }, 56 { "p666", ROCKCHIP_OUT_MODE_P666 }, 57 { "p565", ROCKCHIP_OUT_MODE_P565 }, 58 { "s888", ROCKCHIP_OUT_MODE_S888 }, 59 { "s888_dummy", ROCKCHIP_OUT_MODE_S888_DUMMY } 60 }; 61 int i; 62 63 for (i = 0; i < ARRAY_SIZE(formats); i++) 64 if (!strncmp(s, formats[i].name, strlen(formats[i].name))) 65 return formats[i].format; 66 67 return ROCKCHIP_OUT_MODE_P888; 68 } 69 70 static int rockchip_rgb_init(struct display_state *state) 71 { 72 struct connector_state *conn_state = &state->conn_state; 73 struct panel_state *panel_state = &state->panel_state; 74 const char *mode; 75 76 conn_state->type = DRM_MODE_CONNECTOR_LVDS; 77 conn_state->color_space = V4L2_COLORSPACE_DEFAULT; 78 79 mode = dev_read_string(panel_state->dev, "rgb-mode"); 80 if (mode) 81 conn_state->output_mode = to_output_mode(mode); 82 else 83 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 84 85 return 0; 86 } 87 88 static const struct rockchip_connector_funcs rockchip_rgb_funcs = { 89 .init = rockchip_rgb_init, 90 .enable = rockchip_rgb_prepare, 91 .disable = rockchip_rgb_unprepare, 92 }; 93 94 static int rockchip_rgb_probe(struct udevice *dev) 95 { 96 struct rockchip_rgb_priv *priv = dev_get_priv(dev); 97 98 priv->grf = syscon_get_regmap(dev_get_parent(dev)); 99 100 return 0; 101 } 102 103 static const struct rockchip_connector rockchip_rgb_data = { 104 .funcs = &rockchip_rgb_funcs, 105 }; 106 107 static const struct udevice_id rockchip_rgb_ids[] = { 108 { 109 .compatible = "rockchip,px30-rgb", 110 .data = (ulong)&rockchip_rgb_data, 111 }, 112 { 113 .compatible = "rockchip,rk3066-rgb", 114 .data = (ulong)&rockchip_rgb_data, 115 }, 116 { 117 .compatible = "rockchip,rk3308-rgb", 118 .data = (ulong)&rockchip_rgb_data, 119 }, 120 { 121 .compatible = "rockchip,rv1108-rgb", 122 .data = (ulong)&rockchip_rgb_data, 123 }, 124 {} 125 }; 126 127 U_BOOT_DRIVER(rockchip_rgb) = { 128 .name = "rockchip_rgb", 129 .id = UCLASS_DISPLAY, 130 .of_match = rockchip_rgb_ids, 131 .probe = rockchip_rgb_probe, 132 .priv_auto_alloc_size = sizeof(struct rockchip_rgb_priv), 133 }; 134