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 #include <linux/media-bus-format.h> 14 15 #include "rockchip_display.h" 16 #include "rockchip_crtc.h" 17 #include "rockchip_connector.h" 18 19 #define PX30_GRF_PD_VO_CON1 0x0438 20 #define PX30_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3) 21 #define PX30_RGB_VOP_SEL(v) HIWORD_UPDATE(v, 2, 2) 22 23 #define RK1808_GRF_PD_VO_CON1 0x0444 24 #define RK1808_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3) 25 26 struct rockchip_rgb; 27 28 struct rockchip_rgb_funcs { 29 void (*enable)(struct rockchip_rgb *rgb, int pipe); 30 void (*disable)(struct rockchip_rgb *rgb); 31 }; 32 33 struct rockchip_rgb { 34 struct regmap *grf; 35 const struct rockchip_rgb_funcs *funcs; 36 }; 37 38 static inline struct rockchip_rgb *state_to_rgb(struct display_state *state) 39 { 40 struct connector_state *conn_state = &state->conn_state; 41 42 return dev_get_priv(conn_state->dev); 43 } 44 45 static int rockchip_rgb_connector_enable(struct display_state *state) 46 { 47 struct rockchip_rgb *rgb = state_to_rgb(state); 48 struct crtc_state *crtc_state = &state->crtc_state; 49 int pipe = crtc_state->crtc_id; 50 51 if (rgb->funcs && rgb->funcs->enable) 52 rgb->funcs->enable(rgb, pipe); 53 54 return 0; 55 } 56 57 static int rockchip_rgb_connector_disable(struct display_state *state) 58 { 59 struct rockchip_rgb *rgb = state_to_rgb(state); 60 61 if (rgb->funcs && rgb->funcs->disable) 62 rgb->funcs->disable(rgb); 63 64 return 0; 65 } 66 67 static int rockchip_rgb_connector_init(struct display_state *state) 68 { 69 struct connector_state *conn_state = &state->conn_state; 70 71 conn_state->type = DRM_MODE_CONNECTOR_LVDS; 72 conn_state->color_space = V4L2_COLORSPACE_DEFAULT; 73 74 switch (conn_state->bus_format) { 75 case MEDIA_BUS_FMT_RGB666_1X18: 76 conn_state->output_mode = ROCKCHIP_OUT_MODE_P666; 77 break; 78 case MEDIA_BUS_FMT_RGB565_1X16: 79 conn_state->output_mode = ROCKCHIP_OUT_MODE_P565; 80 break; 81 case MEDIA_BUS_FMT_RGB888_1X24: 82 case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 83 default: 84 conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 85 break; 86 } 87 88 return 0; 89 } 90 91 static const struct rockchip_connector_funcs rockchip_rgb_connector_funcs = { 92 .init = rockchip_rgb_connector_init, 93 .enable = rockchip_rgb_connector_enable, 94 .disable = rockchip_rgb_connector_disable, 95 }; 96 97 static int rockchip_rgb_probe(struct udevice *dev) 98 { 99 struct rockchip_rgb *rgb = dev_get_priv(dev); 100 const struct rockchip_connector *connector = 101 (const struct rockchip_connector *)dev_get_driver_data(dev); 102 103 rgb->funcs = connector->data; 104 rgb->grf = syscon_get_regmap(dev_get_parent(dev)); 105 106 return 0; 107 } 108 109 static void px30_rgb_enable(struct rockchip_rgb *rgb, int pipe) 110 { 111 regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, 112 PX30_RGB_VOP_SEL(pipe)); 113 regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, 114 PX30_RGB_DATA_SYNC_BYPASS(1)); 115 } 116 117 static void px30_rgb_disable(struct rockchip_rgb *rgb) 118 { 119 regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, 120 PX30_RGB_DATA_SYNC_BYPASS(0)); 121 } 122 123 static const struct rockchip_rgb_funcs px30_rgb_funcs = { 124 .enable = px30_rgb_enable, 125 .disable = px30_rgb_disable, 126 }; 127 128 static const struct rockchip_connector px30_rgb_driver_data = { 129 .funcs = &rockchip_rgb_connector_funcs, 130 .data = &px30_rgb_funcs, 131 }; 132 133 static void rk1808_rgb_enable(struct rockchip_rgb *rgb, int pipe) 134 { 135 regmap_write(rgb->grf, RK1808_GRF_PD_VO_CON1, 136 RK1808_RGB_DATA_SYNC_BYPASS(1)); 137 } 138 139 static void rk1808_rgb_disable(struct rockchip_rgb *rgb) 140 { 141 regmap_write(rgb->grf, RK1808_GRF_PD_VO_CON1, 142 RK1808_RGB_DATA_SYNC_BYPASS(0)); 143 } 144 145 static const struct rockchip_rgb_funcs rk1808_rgb_funcs = { 146 .enable = rk1808_rgb_enable, 147 .disable = rk1808_rgb_disable, 148 }; 149 150 static const struct rockchip_connector rk1808_rgb_driver_data = { 151 .funcs = &rockchip_rgb_connector_funcs, 152 .data = &rk1808_rgb_funcs, 153 }; 154 155 static const struct rockchip_connector rockchip_rgb_driver_data = { 156 .funcs = &rockchip_rgb_connector_funcs, 157 }; 158 159 static const struct udevice_id rockchip_rgb_ids[] = { 160 { 161 .compatible = "rockchip,px30-rgb", 162 .data = (ulong)&px30_rgb_driver_data, 163 }, 164 { 165 .compatible = "rockchip,rk1808-rgb", 166 .data = (ulong)&rk1808_rgb_driver_data, 167 }, 168 { 169 .compatible = "rockchip,rk3066-rgb", 170 .data = (ulong)&rockchip_rgb_driver_data, 171 }, 172 { 173 .compatible = "rockchip,rk3308-rgb", 174 .data = (ulong)&rockchip_rgb_driver_data, 175 }, 176 { 177 .compatible = "rockchip,rv1108-rgb", 178 .data = (ulong)&rockchip_rgb_driver_data, 179 }, 180 {} 181 }; 182 183 U_BOOT_DRIVER(rockchip_rgb) = { 184 .name = "rockchip_rgb", 185 .id = UCLASS_DISPLAY, 186 .of_match = rockchip_rgb_ids, 187 .probe = rockchip_rgb_probe, 188 .priv_auto_alloc_size = sizeof(struct rockchip_rgb), 189 }; 190