.. | .. |
---|
83 | 83 | enum lvds_format { |
---|
84 | 84 | LVDS_8BIT_MODE_FORMAT_1, |
---|
85 | 85 | LVDS_8BIT_MODE_FORMAT_2, |
---|
86 | | - LVDS_8BIT_MODE_FORMAT_3, |
---|
87 | | - LVDS_6BIT_MODE, |
---|
| 86 | + LVDS_6BIT_MODE_FORMAT_1, |
---|
| 87 | + LVDS_6BIT_MODE_FORMAT_2, |
---|
88 | 88 | LVDS_10BIT_MODE_FORMAT_1, |
---|
89 | 89 | LVDS_10BIT_MODE_FORMAT_2, |
---|
| 90 | +}; |
---|
| 91 | + |
---|
| 92 | +enum rockchip_lvds_dual_link_pixels { |
---|
| 93 | + ROCKCHIP_LVDS_DUAL_LINK_EVEN_ODD_PIXELS = 0, |
---|
| 94 | + ROCKCHIP_LVDS_DUAL_LINK_ODD_EVEN_PIXELS = 1, |
---|
| 95 | + ROCKCHIP_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS = 2, |
---|
| 96 | + ROCKCHIP_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS = 3, |
---|
| 97 | +}; |
---|
| 98 | + |
---|
| 99 | +enum rockchip_of_lvds_pixels { |
---|
| 100 | + ROCKCHIP_OF_LVDS_EVEN = BIT(0), |
---|
| 101 | + ROCKCHIP_OF_LVDS_ODD = BIT(1), |
---|
| 102 | + ROCKCHIP_OF_LVDS_LEFT = BIT(2), |
---|
| 103 | + ROCKCHIP_OF_LVDS_RIGHT = BIT(3), |
---|
90 | 104 | }; |
---|
91 | 105 | |
---|
92 | 106 | struct rockchip_lvds; |
---|
.. | .. |
---|
107 | 121 | bool data_swap; |
---|
108 | 122 | bool dual_channel; |
---|
109 | 123 | bool phy_enabled; |
---|
110 | | - enum drm_lvds_dual_link_pixels pixel_order; |
---|
| 124 | + enum rockchip_lvds_dual_link_pixels pixel_order; |
---|
111 | 125 | |
---|
112 | 126 | struct rockchip_lvds *primary; |
---|
113 | 127 | struct rockchip_lvds *secondary; |
---|
.. | .. |
---|
119 | 133 | struct drm_display_mode mode; |
---|
120 | 134 | struct rockchip_drm_sub_dev sub_dev; |
---|
121 | 135 | }; |
---|
| 136 | + |
---|
| 137 | +static int rockchip_of_lvds_get_port_pixels_type(struct device_node *port_node) |
---|
| 138 | +{ |
---|
| 139 | + bool even_pixels = |
---|
| 140 | + of_property_read_bool(port_node, "dual-lvds-even-pixels"); |
---|
| 141 | + bool odd_pixels = |
---|
| 142 | + of_property_read_bool(port_node, "dual-lvds-odd-pixels"); |
---|
| 143 | + bool left_pixels = |
---|
| 144 | + of_property_read_bool(port_node, "dual-lvds-left-pixels"); |
---|
| 145 | + bool right_pixels = |
---|
| 146 | + of_property_read_bool(port_node, "dual-lvds-right-pixels"); |
---|
| 147 | + |
---|
| 148 | + return (even_pixels ? ROCKCHIP_OF_LVDS_EVEN : 0) | |
---|
| 149 | + (odd_pixels ? ROCKCHIP_OF_LVDS_ODD : 0) | |
---|
| 150 | + (left_pixels ? ROCKCHIP_OF_LVDS_LEFT : 0) | |
---|
| 151 | + (right_pixels ? ROCKCHIP_OF_LVDS_RIGHT : 0); |
---|
| 152 | +} |
---|
| 153 | + |
---|
| 154 | +static int rockchip_of_lvds_get_remote_pixels_type( |
---|
| 155 | + const struct device_node *port_node) |
---|
| 156 | +{ |
---|
| 157 | + struct device_node *endpoint = NULL; |
---|
| 158 | + int pixels_type = -EPIPE; |
---|
| 159 | + |
---|
| 160 | + for_each_child_of_node(port_node, endpoint) { |
---|
| 161 | + struct device_node *remote_port; |
---|
| 162 | + int current_pt; |
---|
| 163 | + |
---|
| 164 | + if (!of_node_name_eq(endpoint, "endpoint")) |
---|
| 165 | + continue; |
---|
| 166 | + |
---|
| 167 | + remote_port = of_graph_get_remote_port(endpoint); |
---|
| 168 | + if (!remote_port) { |
---|
| 169 | + of_node_put(endpoint); |
---|
| 170 | + return -EPIPE; |
---|
| 171 | + } |
---|
| 172 | + |
---|
| 173 | + current_pt = rockchip_of_lvds_get_port_pixels_type(remote_port); |
---|
| 174 | + of_node_put(remote_port); |
---|
| 175 | + if (pixels_type < 0) |
---|
| 176 | + pixels_type = current_pt; |
---|
| 177 | + |
---|
| 178 | + /* |
---|
| 179 | + * Sanity check, ensure that all remote endpoints have the same |
---|
| 180 | + * pixel type. We may lift this restriction later if we need to |
---|
| 181 | + * support multiple sinks with different dual-link |
---|
| 182 | + * configurations by passing the endpoints explicitly to |
---|
| 183 | + * rockchip_of_lvds_get_dual_link_pixel_order(). |
---|
| 184 | + */ |
---|
| 185 | + if (!current_pt || pixels_type != current_pt) { |
---|
| 186 | + of_node_put(endpoint); |
---|
| 187 | + return -EINVAL; |
---|
| 188 | + } |
---|
| 189 | + } |
---|
| 190 | + |
---|
| 191 | + return pixels_type; |
---|
| 192 | +} |
---|
| 193 | + |
---|
| 194 | +static int rockchip_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, |
---|
| 195 | + const struct device_node *port2) |
---|
| 196 | +{ |
---|
| 197 | + int remote_p1_pt, remote_p2_pt; |
---|
| 198 | + |
---|
| 199 | + if (!port1 || !port2) |
---|
| 200 | + return -EINVAL; |
---|
| 201 | + |
---|
| 202 | + remote_p1_pt = rockchip_of_lvds_get_remote_pixels_type(port1); |
---|
| 203 | + if (remote_p1_pt < 0) |
---|
| 204 | + return remote_p1_pt; |
---|
| 205 | + |
---|
| 206 | + remote_p2_pt = rockchip_of_lvds_get_remote_pixels_type(port2); |
---|
| 207 | + if (remote_p2_pt < 0) |
---|
| 208 | + return remote_p2_pt; |
---|
| 209 | + |
---|
| 210 | + /* |
---|
| 211 | + * A valid dual-lVDS bus is found when one remote port is marked with |
---|
| 212 | + * "dual-lvds-even-pixels" or "dual-lvds-left-pixels", and the other |
---|
| 213 | + * remote port is marked with "dual-lvds-odd-pixels"or |
---|
| 214 | + * "dual-lvds-right-pixels", bail out if the markers are not right. |
---|
| 215 | + */ |
---|
| 216 | + if ((remote_p1_pt + remote_p2_pt != ROCKCHIP_OF_LVDS_EVEN + ROCKCHIP_OF_LVDS_ODD) && |
---|
| 217 | + (remote_p1_pt + remote_p2_pt != ROCKCHIP_OF_LVDS_LEFT + ROCKCHIP_OF_LVDS_RIGHT)) |
---|
| 218 | + return -EINVAL; |
---|
| 219 | + |
---|
| 220 | + if (remote_p1_pt == ROCKCHIP_OF_LVDS_EVEN) |
---|
| 221 | + return ROCKCHIP_LVDS_DUAL_LINK_EVEN_ODD_PIXELS; |
---|
| 222 | + else if (remote_p1_pt == ROCKCHIP_OF_LVDS_ODD) |
---|
| 223 | + return ROCKCHIP_LVDS_DUAL_LINK_ODD_EVEN_PIXELS; |
---|
| 224 | + else if (remote_p1_pt == ROCKCHIP_OF_LVDS_LEFT) |
---|
| 225 | + return ROCKCHIP_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS; |
---|
| 226 | + else |
---|
| 227 | + return ROCKCHIP_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS; |
---|
| 228 | +} |
---|
122 | 229 | |
---|
123 | 230 | static inline struct rockchip_lvds *connector_to_lvds(struct drm_connector *c) |
---|
124 | 231 | { |
---|
.. | .. |
---|
190 | 297 | case MEDIA_BUS_FMT_RGB101010_1X7X5_JEIDA: /* jeida-30 */ |
---|
191 | 298 | lvds->format = LVDS_10BIT_MODE_FORMAT_2; |
---|
192 | 299 | break; |
---|
193 | | - case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: /* vesa-18 */ |
---|
194 | | - lvds->format = LVDS_8BIT_MODE_FORMAT_3; |
---|
| 300 | + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: /* jeida-18, compatible with the [JEIDA], [LDI] and [VESA] specifications */ |
---|
| 301 | + lvds->format = LVDS_6BIT_MODE_FORMAT_1; |
---|
195 | 302 | break; |
---|
196 | 303 | case MEDIA_BUS_FMT_RGB101010_1X7X5_SPWG: /* vesa-30 */ |
---|
197 | 304 | lvds->format = LVDS_10BIT_MODE_FORMAT_1; |
---|
.. | .. |
---|
236 | 343 | s->color_space = V4L2_COLORSPACE_DEFAULT; |
---|
237 | 344 | |
---|
238 | 345 | switch (lvds->pixel_order) { |
---|
239 | | - case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: |
---|
| 346 | + case ROCKCHIP_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: |
---|
240 | 347 | s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE; |
---|
241 | 348 | s->output_if |= VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0; |
---|
242 | 349 | break; |
---|
243 | | - case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: |
---|
| 350 | + case ROCKCHIP_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: |
---|
244 | 351 | s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_ODD_EVEN_MODE; |
---|
245 | 352 | s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP; |
---|
246 | 353 | s->output_if |= VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0; |
---|
247 | 354 | break; |
---|
248 | | -/* |
---|
249 | | - * Fix me: To do it with a GKI compatible version. |
---|
250 | | - */ |
---|
251 | | -#if 0 |
---|
252 | | - case DRM_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS: |
---|
| 355 | + case ROCKCHIP_LVDS_DUAL_LINK_LEFT_RIGHT_PIXELS: |
---|
253 | 356 | s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; |
---|
254 | 357 | s->output_if |= VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0; |
---|
255 | 358 | break; |
---|
256 | | - case DRM_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS: |
---|
| 359 | + case ROCKCHIP_LVDS_DUAL_LINK_RIGHT_LEFT_PIXELS: |
---|
257 | 360 | s->output_flags |= ROCKCHIP_OUTPUT_DUAL_CHANNEL_LEFT_RIGHT_MODE; |
---|
258 | 361 | s->output_flags |= ROCKCHIP_OUTPUT_DATA_SWAP; |
---|
259 | 362 | s->output_if |= VOP_OUTPUT_IF_LVDS1 | VOP_OUTPUT_IF_LVDS0; |
---|
260 | 363 | break; |
---|
261 | | -#endif |
---|
262 | 364 | default: |
---|
263 | 365 | if (lvds->id) |
---|
264 | 366 | s->output_if |= VOP_OUTPUT_IF_LVDS1; |
---|
.. | .. |
---|
646 | 748 | .disable = rk3368_lvds_disable, |
---|
647 | 749 | }; |
---|
648 | 750 | |
---|
649 | | -static int __maybe_unused rockchip_secondary_lvds_probe(struct rockchip_lvds *lvds) |
---|
| 751 | +static int rk3568_lvds_probe(struct rockchip_lvds *lvds) |
---|
650 | 752 | { |
---|
651 | 753 | if (lvds->dual_channel) { |
---|
652 | 754 | struct rockchip_lvds *secondary = NULL; |
---|
.. | .. |
---|
659 | 761 | |
---|
660 | 762 | port0 = of_graph_get_port_by_id(lvds->dev->of_node, 1); |
---|
661 | 763 | port1 = of_graph_get_port_by_id(secondary->dev->of_node, 1); |
---|
662 | | - pixel_order = drm_of_lvds_get_dual_link_pixel_order(port0, port1); |
---|
| 764 | + pixel_order = rockchip_of_lvds_get_dual_link_pixel_order(port0, port1); |
---|
663 | 765 | of_node_put(port1); |
---|
664 | 766 | of_node_put(port0); |
---|
665 | 767 | |
---|
.. | .. |
---|
692 | 794 | |
---|
693 | 795 | static void rk3568_lvds_enable(struct rockchip_lvds *lvds) |
---|
694 | 796 | { |
---|
695 | | - regmap_write(lvds->grf, RK3568_GRF_VO_CON2, |
---|
696 | | - RK3568_LVDS0_MODE_EN(1) | RK3568_LVDS0_P2S_EN(1) | |
---|
697 | | - RK3568_LVDS0_DCLK_INV_SEL(1)); |
---|
698 | | - regmap_write(lvds->grf, RK3568_GRF_VO_CON0, |
---|
699 | | - RK3568_LVDS0_SELECT(lvds->format) | RK3568_LVDS0_MSBSEL(1)); |
---|
| 797 | + if (lvds->id) { |
---|
| 798 | + regmap_write(lvds->grf, RK3568_GRF_VO_CON3, |
---|
| 799 | + RK3568_LVDS1_MODE_EN(1) | |
---|
| 800 | + RK3568_LVDS1_P2S_EN(1) | |
---|
| 801 | + RK3568_LVDS1_DCLK_INV_SEL(1)); |
---|
| 802 | + regmap_write(lvds->grf, RK3568_GRF_VO_CON0, |
---|
| 803 | + RK3568_LVDS1_SELECT(lvds->format) | |
---|
| 804 | + RK3568_LVDS1_MSBSEL(1)); |
---|
| 805 | + } else { |
---|
| 806 | + regmap_write(lvds->grf, RK3568_GRF_VO_CON2, |
---|
| 807 | + RK3568_LVDS0_MODE_EN(1) | |
---|
| 808 | + RK3568_LVDS0_P2S_EN(1) | |
---|
| 809 | + RK3568_LVDS0_DCLK_INV_SEL(1)); |
---|
| 810 | + regmap_write(lvds->grf, RK3568_GRF_VO_CON0, |
---|
| 811 | + RK3568_LVDS0_SELECT(lvds->format) | |
---|
| 812 | + RK3568_LVDS0_MSBSEL(1)); |
---|
| 813 | + } |
---|
700 | 814 | } |
---|
701 | 815 | |
---|
702 | 816 | static void rk3568_lvds_disable(struct rockchip_lvds *lvds) |
---|
703 | 817 | { |
---|
704 | | - regmap_write(lvds->grf, RK3568_GRF_VO_CON2, RK3568_LVDS0_MODE_EN(0)); |
---|
| 818 | + if (lvds->id) |
---|
| 819 | + regmap_write(lvds->grf, RK3568_GRF_VO_CON3, |
---|
| 820 | + RK3568_LVDS1_MODE_EN(0)); |
---|
| 821 | + else |
---|
| 822 | + regmap_write(lvds->grf, RK3568_GRF_VO_CON2, |
---|
| 823 | + RK3568_LVDS0_MODE_EN(0)); |
---|
705 | 824 | } |
---|
706 | 825 | |
---|
707 | 826 | static const struct rockchip_lvds_funcs rk3568_lvds_funcs = { |
---|
| 827 | + .probe = rk3568_lvds_probe, |
---|
708 | 828 | .enable = rk3568_lvds_enable, |
---|
709 | 829 | .disable = rk3568_lvds_disable, |
---|
710 | 830 | }; |
---|