19e02a86eSWyon Bi /* 29e02a86eSWyon Bi * (C) Copyright 2008-2017 Fuzhou Rockchip Electronics Co., Ltd 39e02a86eSWyon Bi * 49e02a86eSWyon Bi * SPDX-License-Identifier: GPL-2.0+ 59e02a86eSWyon Bi */ 69e02a86eSWyon Bi 79e02a86eSWyon Bi #include <common.h> 8cb17ca6cSSandy Huang #include <dm/of_access.h> 99e02a86eSWyon Bi #include <errno.h> 109e02a86eSWyon Bi #include <syscon.h> 119e02a86eSWyon Bi #include <regmap.h> 129e02a86eSWyon Bi #include <dm/device.h> 139e02a86eSWyon Bi #include <dm/read.h> 14350f6a18SWyon Bi #include <dm/pinctrl.h> 156b93bf2bSWyon Bi #include <linux/media-bus-format.h> 16b5dbb15aSDamon Ding #include <asm/gpio.h> 17b5dbb15aSDamon Ding #include <backlight.h> 189e02a86eSWyon Bi 199e02a86eSWyon Bi #include "rockchip_display.h" 209e02a86eSWyon Bi #include "rockchip_crtc.h" 219e02a86eSWyon Bi #include "rockchip_connector.h" 2249627130SWyon Bi #include "rockchip_phy.h" 23b5dbb15aSDamon Ding #include "rockchip_panel.h" 249e02a86eSWyon Bi 251953e619SWyon Bi #define HIWORD_UPDATE(v, h, l) (((v) << (l)) | (GENMASK(h, l) << 16)) 261953e619SWyon Bi 279e02a86eSWyon Bi #define PX30_GRF_PD_VO_CON1 0x0438 286b9c0415SSandy Huang #define PX30_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3) 299e02a86eSWyon Bi #define PX30_RGB_VOP_SEL(v) HIWORD_UPDATE(v, 2, 2) 309e02a86eSWyon Bi 316b9c0415SSandy Huang #define RK1808_GRF_PD_VO_CON1 0x0444 326b9c0415SSandy Huang #define RK1808_RGB_DATA_SYNC_BYPASS(v) HIWORD_UPDATE(v, 3, 3) 336b9c0415SSandy Huang 34e8dd2b64SDamon Ding #define RV1106_VENC_GRF_VOP_IO_WRAPPER 0x1000c 35e8dd2b64SDamon Ding #define RV1106_IO_BYPASS_SEL(v) HIWORD_UPDATE(v, 0, 1) 36e8dd2b64SDamon Ding #define RV1106_VOGRF_VOP_PIPE_BYPASS 0x60034 37e8dd2b64SDamon Ding #define RV1106_VOP_PIPE_BYPASS(v) HIWORD_UPDATE(v, 0, 1) 38e8dd2b64SDamon Ding 39406bb09aSAndy Yan #define RV1126_GRF_IOFUNC_CON3 0x1026c 40406bb09aSAndy Yan #define RV1126_LCDC_IO_BYPASS(v) HIWORD_UPDATE(v, 0, 0) 41406bb09aSAndy Yan 4249627130SWyon Bi #define RK3288_GRF_SOC_CON6 0x025c 4349627130SWyon Bi #define RK3288_LVDS_LCDC_SEL(v) HIWORD_UPDATE(v, 3, 3) 4449627130SWyon Bi #define RK3288_GRF_SOC_CON7 0x0260 4549627130SWyon Bi #define RK3288_LVDS_PWRDWN(v) HIWORD_UPDATE(v, 15, 15) 4649627130SWyon Bi #define RK3288_LVDS_CON_ENABLE_2(v) HIWORD_UPDATE(v, 12, 12) 4749627130SWyon Bi #define RK3288_LVDS_CON_ENABLE_1(v) HIWORD_UPDATE(v, 11, 11) 4849627130SWyon Bi #define RK3288_LVDS_CON_CLKINV(v) HIWORD_UPDATE(v, 8, 8) 4949627130SWyon Bi #define RK3288_LVDS_CON_TTL_EN(v) HIWORD_UPDATE(v, 6, 6) 5049627130SWyon Bi 516383df2bSSandy Huang #define RK3368_GRF_SOC_CON15 0x043c 526383df2bSSandy Huang #define RK3368_FORCE_JETAG(v) HIWORD_UPDATE(v, 13, 13) 536383df2bSSandy Huang 54078f1c2cSDamon Ding #define RK3562_GRF_IOC_VO_IO_CON 0x10500 55078f1c2cSDamon Ding #define RK3562_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6) 56078f1c2cSDamon Ding 57c55d261eSSandy Huang #define RK3568_GRF_VO_CON1 0X0364 58c55d261eSSandy Huang #define RK3568_RGB_DATA_BYPASS(v) HIWORD_UPDATE(v, 6, 6) 59c55d261eSSandy Huang 60181a4463SDamon Ding #define RK3576_VCCIO_IOC_MISC_CON8 0x6420 61181a4463SDamon Ding #define RK3576_VOP_MCU_SEL(v) HIWORD_UPDATE(v, 10, 10) 62*0fd9ded2SDamon Ding #define RK3576_VOP_DLL_SEL(v) HIWORD_UPDATE(v, 8, 8) 63*0fd9ded2SDamon Ding #define RK3576_VOP_DCLK_DELAYLINE(v) HIWORD_UPDATE(v, 0, 6) 64181a4463SDamon Ding 656b9c0415SSandy Huang struct rockchip_rgb; 666b9c0415SSandy Huang 676b9c0415SSandy Huang struct rockchip_rgb_funcs { 684ec7b4d4SSandy Huang void (*prepare)(struct rockchip_rgb *rgb, int pipe); 694ec7b4d4SSandy Huang void (*unprepare)(struct rockchip_rgb *rgb); 709e02a86eSWyon Bi }; 719e02a86eSWyon Bi 724ed82c15SDamon Ding struct rockchip_rgb_data { 734ed82c15SDamon Ding u32 rgb_max_dclk_rate; 744ed82c15SDamon Ding u32 mcu_max_dclk_rate; 75*0fd9ded2SDamon Ding u32 dclk_delayline; 764ed82c15SDamon Ding const struct rockchip_rgb_funcs *funcs; 774ed82c15SDamon Ding }; 784ed82c15SDamon Ding 796b9c0415SSandy Huang struct rockchip_rgb { 800594ce39SZhang Yubing struct rockchip_connector connector; 81cb17ca6cSSandy Huang int id; 8249627130SWyon Bi struct udevice *dev; 836b9c0415SSandy Huang struct regmap *grf; 84406bb09aSAndy Yan bool data_sync_bypass; 8549627130SWyon Bi struct rockchip_phy *phy; 866b9c0415SSandy Huang const struct rockchip_rgb_funcs *funcs; 874ed82c15SDamon Ding u32 max_dclk_rate; 88*0fd9ded2SDamon Ding u32 dclk_delayline; 896b9c0415SSandy Huang }; 906b9c0415SSandy Huang 91b5dbb15aSDamon Ding struct mcu_cmd_header { 92b5dbb15aSDamon Ding u8 data_type; 93b5dbb15aSDamon Ding u8 delay; 94b5dbb15aSDamon Ding u8 payload_length; 95b5dbb15aSDamon Ding } __packed; 96b5dbb15aSDamon Ding 97b5dbb15aSDamon Ding struct mcu_cmd_desc { 98b5dbb15aSDamon Ding struct mcu_cmd_header header; 99b5dbb15aSDamon Ding const u8 *payload; 100b5dbb15aSDamon Ding }; 101b5dbb15aSDamon Ding 102b5dbb15aSDamon Ding struct mcu_cmd_seq { 103b5dbb15aSDamon Ding struct mcu_cmd_desc *cmds; 104b5dbb15aSDamon Ding unsigned int cmd_cnt; 105b5dbb15aSDamon Ding }; 106b5dbb15aSDamon Ding 107b5dbb15aSDamon Ding struct rockchip_mcu_panel_desc { 108b5dbb15aSDamon Ding struct mcu_cmd_seq *init_seq; 109b5dbb15aSDamon Ding struct mcu_cmd_seq *exit_seq; 110b5dbb15aSDamon Ding 111b5dbb15aSDamon Ding struct { 112b5dbb15aSDamon Ding unsigned int width; 113b5dbb15aSDamon Ding unsigned int height; 114b5dbb15aSDamon Ding } size; 115b5dbb15aSDamon Ding 116b5dbb15aSDamon Ding struct { 117b5dbb15aSDamon Ding unsigned int prepare; 118b5dbb15aSDamon Ding unsigned int enable; 119b5dbb15aSDamon Ding unsigned int disable; 120b5dbb15aSDamon Ding unsigned int unprepare; 121b5dbb15aSDamon Ding unsigned int reset; 122b5dbb15aSDamon Ding unsigned int init; 123b5dbb15aSDamon Ding } delay; 124b5dbb15aSDamon Ding 125b5dbb15aSDamon Ding unsigned int bpc; 126b5dbb15aSDamon Ding u32 bus_format; 127b5dbb15aSDamon Ding u32 bus_flags; 128b5dbb15aSDamon Ding bool power_invert; 129b5dbb15aSDamon Ding }; 130b5dbb15aSDamon Ding 131b5dbb15aSDamon Ding struct rockchip_mcu_panel { 132b5dbb15aSDamon Ding struct rockchip_panel base; 133b5dbb15aSDamon Ding struct rockchip_mcu_panel_desc *desc; 134b5dbb15aSDamon Ding struct udevice *power_supply; 135b5dbb15aSDamon Ding struct udevice *backlight; 136b5dbb15aSDamon Ding 137b5dbb15aSDamon Ding struct gpio_desc enable_gpio; 138b5dbb15aSDamon Ding struct gpio_desc reset_gpio; 139b5dbb15aSDamon Ding 140b5dbb15aSDamon Ding bool prepared; 141b5dbb15aSDamon Ding bool enabled; 142b5dbb15aSDamon Ding }; 143b5dbb15aSDamon Ding 144b5dbb15aSDamon Ding static inline struct rockchip_mcu_panel *to_rockchip_mcu_panel(struct rockchip_panel *panel) 145b5dbb15aSDamon Ding { 146b5dbb15aSDamon Ding return container_of(panel, struct rockchip_mcu_panel, base); 147b5dbb15aSDamon Ding } 148b5dbb15aSDamon Ding 1490594ce39SZhang Yubing static int rockchip_rgb_connector_prepare(struct rockchip_connector *conn, 1500594ce39SZhang Yubing struct display_state *state) 1519e02a86eSWyon Bi { 1520594ce39SZhang Yubing struct rockchip_rgb *rgb = dev_get_priv(conn->dev); 1539e02a86eSWyon Bi struct crtc_state *crtc_state = &state->crtc_state; 1549e02a86eSWyon Bi int pipe = crtc_state->crtc_id; 1559e3ffb10SGuochun Huang int ret; 1569e02a86eSWyon Bi 157350f6a18SWyon Bi pinctrl_select_state(rgb->dev, "default"); 158350f6a18SWyon Bi 1594ec7b4d4SSandy Huang if (rgb->funcs && rgb->funcs->prepare) 1604ec7b4d4SSandy Huang rgb->funcs->prepare(rgb, pipe); 1619e02a86eSWyon Bi 1629e3ffb10SGuochun Huang if (rgb->phy) { 1639e3ffb10SGuochun Huang ret = rockchip_phy_set_mode(rgb->phy, PHY_MODE_VIDEO_TTL); 1649e3ffb10SGuochun Huang if (ret) { 1659e3ffb10SGuochun Huang dev_err(rgb->dev, "failed to set phy mode: %d\n", ret); 1669e3ffb10SGuochun Huang return ret; 1679e3ffb10SGuochun Huang } 1685a7ad828SGuochun Huang 1699e3ffb10SGuochun Huang rockchip_phy_power_on(rgb->phy); 1709e3ffb10SGuochun Huang } 17149627130SWyon Bi 1729e02a86eSWyon Bi return 0; 1739e02a86eSWyon Bi } 1749e02a86eSWyon Bi 1750594ce39SZhang Yubing static void rockchip_rgb_connector_unprepare(struct rockchip_connector *conn, 1760594ce39SZhang Yubing struct display_state *state) 1779e02a86eSWyon Bi { 1780594ce39SZhang Yubing struct rockchip_rgb *rgb = dev_get_priv(conn->dev); 1796b9c0415SSandy Huang 18049627130SWyon Bi if (rgb->phy) 18149627130SWyon Bi rockchip_phy_power_off(rgb->phy); 18249627130SWyon Bi 1834ec7b4d4SSandy Huang if (rgb->funcs && rgb->funcs->unprepare) 1844ec7b4d4SSandy Huang rgb->funcs->unprepare(rgb); 1856b9c0415SSandy Huang 186350f6a18SWyon Bi pinctrl_select_state(rgb->dev, "sleep"); 1879e02a86eSWyon Bi } 1889e02a86eSWyon Bi 1890594ce39SZhang Yubing static int rockchip_rgb_connector_init(struct rockchip_connector *conn, struct display_state *state) 19058c17f51SSandy Huang { 1910594ce39SZhang Yubing struct rockchip_rgb *rgb = dev_get_priv(conn->dev); 19258c17f51SSandy Huang struct connector_state *conn_state = &state->conn_state; 19358c17f51SSandy Huang 1940594ce39SZhang Yubing rgb->phy = conn->phy; 19549627130SWyon Bi 196df0a5c43SDamon Ding conn_state->color_range = DRM_COLOR_YCBCR_FULL_RANGE; 197df0a5c43SDamon Ding conn_state->color_encoding = DRM_COLOR_YCBCR_BT709; 198cb17ca6cSSandy Huang conn_state->disp_info = rockchip_get_disp_info(conn_state->type, rgb->id); 1999e02a86eSWyon Bi 2006b93bf2bSWyon Bi switch (conn_state->bus_format) { 2016b93bf2bSWyon Bi case MEDIA_BUS_FMT_RGB666_1X18: 2026b93bf2bSWyon Bi conn_state->output_mode = ROCKCHIP_OUT_MODE_P666; 203c55d261eSSandy Huang conn_state->output_if = VOP_OUTPUT_IF_RGB; 2046b93bf2bSWyon Bi break; 2056b93bf2bSWyon Bi case MEDIA_BUS_FMT_RGB565_1X16: 2066b93bf2bSWyon Bi conn_state->output_mode = ROCKCHIP_OUT_MODE_P565; 207c55d261eSSandy Huang conn_state->output_if = VOP_OUTPUT_IF_RGB; 2086b93bf2bSWyon Bi break; 20901c3fe29SDamon Ding case MEDIA_BUS_FMT_RGB565_2X8_LE: 21001c3fe29SDamon Ding case MEDIA_BUS_FMT_BGR565_2X8_LE: 21101c3fe29SDamon Ding conn_state->output_mode = ROCKCHIP_OUT_MODE_S565; 21201c3fe29SDamon Ding conn_state->output_if = VOP_OUTPUT_IF_RGB; 21301c3fe29SDamon Ding break; 21401c3fe29SDamon Ding case MEDIA_BUS_FMT_RGB666_3X6: 21501c3fe29SDamon Ding conn_state->output_mode = ROCKCHIP_OUT_MODE_S666; 21601c3fe29SDamon Ding conn_state->output_if = VOP_OUTPUT_IF_RGB; 21701c3fe29SDamon Ding break; 218b7b383ebSDamon Ding case MEDIA_BUS_FMT_RGB888_3X8: 219b7b383ebSDamon Ding case MEDIA_BUS_FMT_BGR888_3X8: 220b754d470SYu YongZhen conn_state->output_mode = ROCKCHIP_OUT_MODE_S888; 221c55d261eSSandy Huang conn_state->output_if = VOP_OUTPUT_IF_RGB; 222b754d470SYu YongZhen break; 223b7b383ebSDamon Ding case MEDIA_BUS_FMT_RGB888_DUMMY_4X8: 224b7b383ebSDamon Ding case MEDIA_BUS_FMT_BGR888_DUMMY_4X8: 2254ec7b4d4SSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY; 226c55d261eSSandy Huang conn_state->output_if = VOP_OUTPUT_IF_RGB; 2274ec7b4d4SSandy Huang break; 228c55d261eSSandy Huang case MEDIA_BUS_FMT_YUYV8_2X8: 229c55d261eSSandy Huang case MEDIA_BUS_FMT_YVYU8_2X8: 230c55d261eSSandy Huang case MEDIA_BUS_FMT_UYVY8_2X8: 231c55d261eSSandy Huang case MEDIA_BUS_FMT_VYUY8_2X8: 232c55d261eSSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_BT656; 233c55d261eSSandy Huang conn_state->output_if = VOP_OUTPUT_IF_BT656; 234df0a5c43SDamon Ding conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; 235df0a5c43SDamon Ding conn_state->color_encoding = DRM_COLOR_YCBCR_BT601; 236c55d261eSSandy Huang break; 237c55d261eSSandy Huang case MEDIA_BUS_FMT_YUYV8_1X16: 238c55d261eSSandy Huang case MEDIA_BUS_FMT_YVYU8_1X16: 239c55d261eSSandy Huang case MEDIA_BUS_FMT_UYVY8_1X16: 240c55d261eSSandy Huang case MEDIA_BUS_FMT_VYUY8_1X16: 241c55d261eSSandy Huang conn_state->output_mode = ROCKCHIP_OUT_MODE_BT1120; 242c55d261eSSandy Huang conn_state->output_if = VOP_OUTPUT_IF_BT1120; 243df0a5c43SDamon Ding conn_state->color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; 244d30e58a8SDamon Ding break; 2456b93bf2bSWyon Bi case MEDIA_BUS_FMT_RGB888_1X24: 2466b93bf2bSWyon Bi case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: 2476b93bf2bSWyon Bi default: 2489e02a86eSWyon Bi conn_state->output_mode = ROCKCHIP_OUT_MODE_P888; 249c55d261eSSandy Huang conn_state->output_if = VOP_OUTPUT_IF_RGB; 2506b93bf2bSWyon Bi break; 2516b93bf2bSWyon Bi } 2529e02a86eSWyon Bi 2539e02a86eSWyon Bi return 0; 2549e02a86eSWyon Bi } 2559e02a86eSWyon Bi 2564ed82c15SDamon Ding static int rockchip_rgb_connector_mode_valid(struct rockchip_connector *conn, 2574ed82c15SDamon Ding struct display_state *state) 2584ed82c15SDamon Ding { 2594ed82c15SDamon Ding struct rockchip_rgb *rgb = dev_get_priv(conn->dev); 2604ed82c15SDamon Ding struct connector_state *conn_state = &state->conn_state; 2614ed82c15SDamon Ding struct crtc_state *crtc_state = &state->crtc_state; 2624ed82c15SDamon Ding struct drm_display_mode *mode = &conn_state->mode; 2634ed82c15SDamon Ding u32 request_clock = mode->clock; 2644ed82c15SDamon Ding u32 max_clock = rgb->max_dclk_rate; 2654ed82c15SDamon Ding 2664ed82c15SDamon Ding if (mode->flags & DRM_MODE_FLAG_DBLCLK) 2674ed82c15SDamon Ding request_clock *= 2; 2684ed82c15SDamon Ding 2694ed82c15SDamon Ding if (rgb->data_sync_bypass) 2704ed82c15SDamon Ding request_clock *= rockchip_drm_get_cycles_per_pixel(conn_state->bus_format) * 2714ed82c15SDamon Ding (crtc_state->mcu_timing.mcu_pix_total + 1); 2724ed82c15SDamon Ding 2734ed82c15SDamon Ding if (max_clock != 0 && request_clock > max_clock) { 2744ed82c15SDamon Ding printf("mode [%dx%d] clock %d is higher than max_clock %d\n", 2754ed82c15SDamon Ding mode->hdisplay, mode->vdisplay, request_clock, max_clock); 2764ed82c15SDamon Ding return -EINVAL; 2774ed82c15SDamon Ding } 2784ed82c15SDamon Ding 2794ed82c15SDamon Ding return 0; 2804ed82c15SDamon Ding } 2814ed82c15SDamon Ding 2826b9c0415SSandy Huang static const struct rockchip_connector_funcs rockchip_rgb_connector_funcs = { 2836b9c0415SSandy Huang .init = rockchip_rgb_connector_init, 2844ec7b4d4SSandy Huang .prepare = rockchip_rgb_connector_prepare, 2854ec7b4d4SSandy Huang .unprepare = rockchip_rgb_connector_unprepare, 2864ed82c15SDamon Ding .mode_valid = rockchip_rgb_connector_mode_valid, 2879e02a86eSWyon Bi }; 2889e02a86eSWyon Bi 289b5dbb15aSDamon Ding static int rockchip_mcu_panel_send_cmds(struct display_state *state, 290b5dbb15aSDamon Ding struct mcu_cmd_seq *cmds) 291b5dbb15aSDamon Ding { 292b5dbb15aSDamon Ding int i; 293b5dbb15aSDamon Ding 294b5dbb15aSDamon Ding if (!cmds) 295b5dbb15aSDamon Ding return -EINVAL; 296b5dbb15aSDamon Ding 297b5dbb15aSDamon Ding display_send_mcu_cmd(state, MCU_SETBYPASS, 1); 298b5dbb15aSDamon Ding for (i = 0; i < cmds->cmd_cnt; i++) { 299b5dbb15aSDamon Ding struct mcu_cmd_desc *desc = &cmds->cmds[i]; 300b5dbb15aSDamon Ding int value = 0; 301b5dbb15aSDamon Ding 302b5dbb15aSDamon Ding value = desc->payload[0]; 303b5dbb15aSDamon Ding display_send_mcu_cmd(state, desc->header.data_type, value); 304b5dbb15aSDamon Ding 305b5dbb15aSDamon Ding if (desc->header.delay) 306b5dbb15aSDamon Ding mdelay(desc->header.delay); 307b5dbb15aSDamon Ding } 308b5dbb15aSDamon Ding display_send_mcu_cmd(state, MCU_SETBYPASS, 0); 309b5dbb15aSDamon Ding 310b5dbb15aSDamon Ding return 0; 311b5dbb15aSDamon Ding } 312b5dbb15aSDamon Ding 313b5dbb15aSDamon Ding static void rockchip_mcu_panel_prepare(struct rockchip_panel *panel) 314b5dbb15aSDamon Ding { 315b5dbb15aSDamon Ding struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel); 316b5dbb15aSDamon Ding int ret; 317b5dbb15aSDamon Ding 318b5dbb15aSDamon Ding if (mcu_panel->prepared) 319b5dbb15aSDamon Ding return; 320b5dbb15aSDamon Ding 321b5dbb15aSDamon Ding if (dm_gpio_is_valid(&mcu_panel->enable_gpio)) 322b5dbb15aSDamon Ding dm_gpio_set_value(&mcu_panel->enable_gpio, 1); 323b5dbb15aSDamon Ding 324b5dbb15aSDamon Ding if (mcu_panel->desc->delay.prepare) 325b5dbb15aSDamon Ding mdelay(mcu_panel->desc->delay.prepare); 326b5dbb15aSDamon Ding 327b5dbb15aSDamon Ding if (dm_gpio_is_valid(&mcu_panel->reset_gpio)) 328b5dbb15aSDamon Ding dm_gpio_set_value(&mcu_panel->reset_gpio, 1); 329b5dbb15aSDamon Ding 330b5dbb15aSDamon Ding if (mcu_panel->desc->delay.reset) 331b5dbb15aSDamon Ding mdelay(mcu_panel->desc->delay.reset); 332b5dbb15aSDamon Ding 333b5dbb15aSDamon Ding if (dm_gpio_is_valid(&mcu_panel->reset_gpio)) 334b5dbb15aSDamon Ding dm_gpio_set_value(&mcu_panel->reset_gpio, 0); 335b5dbb15aSDamon Ding 336b5dbb15aSDamon Ding if (mcu_panel->desc->delay.init) 337b5dbb15aSDamon Ding mdelay(mcu_panel->desc->delay.init); 338b5dbb15aSDamon Ding 339b5dbb15aSDamon Ding if (mcu_panel->desc->init_seq) { 340b5dbb15aSDamon Ding ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->init_seq); 341b5dbb15aSDamon Ding if (ret) 342b5dbb15aSDamon Ding printf("failed to send mcu panel init cmds: %d\n", ret); 343b5dbb15aSDamon Ding } 344b5dbb15aSDamon Ding 345b5dbb15aSDamon Ding mcu_panel->prepared = true; 346b5dbb15aSDamon Ding } 347b5dbb15aSDamon Ding 348b5dbb15aSDamon Ding static void rockchip_mcu_panel_unprepare(struct rockchip_panel *panel) 349b5dbb15aSDamon Ding { 350b5dbb15aSDamon Ding struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel); 351b5dbb15aSDamon Ding int ret; 352b5dbb15aSDamon Ding 353b5dbb15aSDamon Ding if (!mcu_panel->prepared) 354b5dbb15aSDamon Ding return; 355b5dbb15aSDamon Ding 356b5dbb15aSDamon Ding if (mcu_panel->desc->exit_seq) { 357b5dbb15aSDamon Ding ret = rockchip_mcu_panel_send_cmds(panel->state, mcu_panel->desc->exit_seq); 358b5dbb15aSDamon Ding if (ret) 359b5dbb15aSDamon Ding printf("failed to send mcu panel exit cmds: %d\n", ret); 360b5dbb15aSDamon Ding } 361b5dbb15aSDamon Ding 362b5dbb15aSDamon Ding if (dm_gpio_is_valid(&mcu_panel->reset_gpio)) 363b5dbb15aSDamon Ding dm_gpio_set_value(&mcu_panel->reset_gpio, 1); 364b5dbb15aSDamon Ding 365b5dbb15aSDamon Ding if (dm_gpio_is_valid(&mcu_panel->enable_gpio)) 366b5dbb15aSDamon Ding dm_gpio_set_value(&mcu_panel->enable_gpio, 0); 367b5dbb15aSDamon Ding 368b5dbb15aSDamon Ding if (mcu_panel->desc->delay.unprepare) 369b5dbb15aSDamon Ding mdelay(mcu_panel->desc->delay.unprepare); 370b5dbb15aSDamon Ding 371b5dbb15aSDamon Ding mcu_panel->prepared = false; 372b5dbb15aSDamon Ding } 373b5dbb15aSDamon Ding 374b5dbb15aSDamon Ding static void rockchip_mcu_panel_enable(struct rockchip_panel *panel) 375b5dbb15aSDamon Ding { 376b5dbb15aSDamon Ding struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel); 377b5dbb15aSDamon Ding 378b5dbb15aSDamon Ding if (mcu_panel->enabled) 379b5dbb15aSDamon Ding return; 380b5dbb15aSDamon Ding 381b5dbb15aSDamon Ding if (mcu_panel->desc->delay.enable) 382b5dbb15aSDamon Ding mdelay(mcu_panel->desc->delay.enable); 383b5dbb15aSDamon Ding 384b5dbb15aSDamon Ding if (mcu_panel->backlight) 385b5dbb15aSDamon Ding backlight_enable(mcu_panel->backlight); 386b5dbb15aSDamon Ding 387b5dbb15aSDamon Ding mcu_panel->enabled = true; 388b5dbb15aSDamon Ding } 389b5dbb15aSDamon Ding 390b5dbb15aSDamon Ding static void rockchip_mcu_panel_disable(struct rockchip_panel *panel) 391b5dbb15aSDamon Ding { 392b5dbb15aSDamon Ding struct rockchip_mcu_panel *mcu_panel = to_rockchip_mcu_panel(panel); 393b5dbb15aSDamon Ding 394b5dbb15aSDamon Ding if (!mcu_panel->enabled) 395b5dbb15aSDamon Ding return; 396b5dbb15aSDamon Ding 397b5dbb15aSDamon Ding if (mcu_panel->backlight) 398b5dbb15aSDamon Ding backlight_disable(mcu_panel->backlight); 399b5dbb15aSDamon Ding 400b5dbb15aSDamon Ding if (mcu_panel->desc->delay.disable) 401b5dbb15aSDamon Ding mdelay(mcu_panel->desc->delay.disable); 402b5dbb15aSDamon Ding 403b5dbb15aSDamon Ding mcu_panel->enabled = false; 404b5dbb15aSDamon Ding } 405b5dbb15aSDamon Ding 406b5dbb15aSDamon Ding static const struct rockchip_panel_funcs rockchip_mcu_panel_funcs = { 407b5dbb15aSDamon Ding .prepare = rockchip_mcu_panel_prepare, 408b5dbb15aSDamon Ding .unprepare = rockchip_mcu_panel_unprepare, 409b5dbb15aSDamon Ding .enable = rockchip_mcu_panel_enable, 410b5dbb15aSDamon Ding .disable = rockchip_mcu_panel_disable, 411b5dbb15aSDamon Ding }; 412b5dbb15aSDamon Ding 413b5dbb15aSDamon Ding static int rockchip_mcu_panel_parse_cmds(const u8 *data, int length, 414b5dbb15aSDamon Ding struct mcu_cmd_seq *pcmds) 415b5dbb15aSDamon Ding { 416b5dbb15aSDamon Ding int len; 417b5dbb15aSDamon Ding const u8 *buf; 418b5dbb15aSDamon Ding const struct mcu_cmd_header *header; 419b5dbb15aSDamon Ding int i, cnt = 0; 420b5dbb15aSDamon Ding 421b5dbb15aSDamon Ding /* scan commands */ 422b5dbb15aSDamon Ding cnt = 0; 423b5dbb15aSDamon Ding buf = data; 424b5dbb15aSDamon Ding len = length; 425b5dbb15aSDamon Ding while (len > sizeof(*header)) { 426b5dbb15aSDamon Ding header = (const struct mcu_cmd_header *)buf; 427b5dbb15aSDamon Ding buf += sizeof(*header) + header->payload_length; 428b5dbb15aSDamon Ding len -= sizeof(*header) + header->payload_length; 429b5dbb15aSDamon Ding cnt++; 430b5dbb15aSDamon Ding } 431b5dbb15aSDamon Ding 432b5dbb15aSDamon Ding pcmds->cmds = calloc(cnt, sizeof(struct mcu_cmd_desc)); 433b5dbb15aSDamon Ding if (!pcmds->cmds) 434b5dbb15aSDamon Ding return -ENOMEM; 435b5dbb15aSDamon Ding 436b5dbb15aSDamon Ding pcmds->cmd_cnt = cnt; 437b5dbb15aSDamon Ding 438b5dbb15aSDamon Ding buf = data; 439b5dbb15aSDamon Ding len = length; 440b5dbb15aSDamon Ding for (i = 0; i < cnt; i++) { 441b5dbb15aSDamon Ding struct mcu_cmd_desc *desc = &pcmds->cmds[i]; 442b5dbb15aSDamon Ding 443b5dbb15aSDamon Ding header = (const struct mcu_cmd_header *)buf; 444b5dbb15aSDamon Ding length -= sizeof(*header); 445b5dbb15aSDamon Ding buf += sizeof(*header); 446b5dbb15aSDamon Ding desc->header.data_type = header->data_type; 447b5dbb15aSDamon Ding desc->header.delay = header->delay; 448b5dbb15aSDamon Ding desc->header.payload_length = header->payload_length; 449b5dbb15aSDamon Ding desc->payload = buf; 450b5dbb15aSDamon Ding buf += header->payload_length; 451b5dbb15aSDamon Ding length -= header->payload_length; 452b5dbb15aSDamon Ding } 453b5dbb15aSDamon Ding 454b5dbb15aSDamon Ding return 0; 455b5dbb15aSDamon Ding } 456b5dbb15aSDamon Ding 457b5dbb15aSDamon Ding static int rockchip_mcu_panel_init(struct rockchip_mcu_panel *mcu_panel, ofnode mcu_panel_node) 458b5dbb15aSDamon Ding { 459b5dbb15aSDamon Ding const void *data; 460b5dbb15aSDamon Ding int len; 461b5dbb15aSDamon Ding int ret; 462b5dbb15aSDamon Ding 463b5dbb15aSDamon Ding ret = gpio_request_by_name_nodev(mcu_panel_node, "enable-gpios", 0, 464b5dbb15aSDamon Ding &mcu_panel->enable_gpio, GPIOD_IS_OUT); 465b5dbb15aSDamon Ding if (ret && ret != -ENOENT) { 466b5dbb15aSDamon Ding printf("%s: Cannot get mcu panel enable GPIO: %d\n", __func__, ret); 467b5dbb15aSDamon Ding return ret; 468b5dbb15aSDamon Ding } 469b5dbb15aSDamon Ding 470b5dbb15aSDamon Ding ret = gpio_request_by_name_nodev(mcu_panel_node, "reset-gpios", 0, 471b5dbb15aSDamon Ding &mcu_panel->reset_gpio, GPIOD_IS_OUT); 472b5dbb15aSDamon Ding if (ret && ret != -ENOENT) { 473b5dbb15aSDamon Ding printf("%s: Cannot get mcu panel reset GPIO: %d\n", __func__, ret); 474b5dbb15aSDamon Ding return ret; 475b5dbb15aSDamon Ding } 476b5dbb15aSDamon Ding 477b5dbb15aSDamon Ding mcu_panel->desc = malloc(sizeof(struct rockchip_mcu_panel_desc)); 478b5dbb15aSDamon Ding if (!mcu_panel->desc) 479b5dbb15aSDamon Ding return -ENOMEM; 480b5dbb15aSDamon Ding 481b5dbb15aSDamon Ding mcu_panel->desc->power_invert = ofnode_read_bool(mcu_panel_node, "power-invert"); 482b5dbb15aSDamon Ding 483b5dbb15aSDamon Ding mcu_panel->desc->delay.prepare = ofnode_read_u32_default(mcu_panel_node, "prepare-delay-ms", 0); 484b5dbb15aSDamon Ding mcu_panel->desc->delay.unprepare = ofnode_read_u32_default(mcu_panel_node, "unprepare-delay-ms", 0); 485b5dbb15aSDamon Ding mcu_panel->desc->delay.enable = ofnode_read_u32_default(mcu_panel_node, "enable-delay-ms", 0); 486b5dbb15aSDamon Ding mcu_panel->desc->delay.disable = ofnode_read_u32_default(mcu_panel_node, "disable-delay-ms", 0); 487b5dbb15aSDamon Ding mcu_panel->desc->delay.init = ofnode_read_u32_default(mcu_panel_node, "init-delay-ms", 0); 488b5dbb15aSDamon Ding mcu_panel->desc->delay.reset = ofnode_read_u32_default(mcu_panel_node, "reset-delay-ms", 0); 489b5dbb15aSDamon Ding 490b5dbb15aSDamon Ding mcu_panel->desc->bus_format = ofnode_read_u32_default(mcu_panel_node, "bus-format", 491b5dbb15aSDamon Ding MEDIA_BUS_FMT_RBG888_1X24); 492b5dbb15aSDamon Ding mcu_panel->desc->bpc = ofnode_read_u32_default(mcu_panel_node, "bpc", 8); 493b5dbb15aSDamon Ding 494b5dbb15aSDamon Ding data = ofnode_get_property(mcu_panel_node, "panel-init-sequence", &len); 495b5dbb15aSDamon Ding if (data) { 496b5dbb15aSDamon Ding mcu_panel->desc->init_seq = calloc(1, sizeof(*mcu_panel->desc->init_seq)); 497b5dbb15aSDamon Ding if (!mcu_panel->desc->init_seq) 498b5dbb15aSDamon Ding return -ENOMEM; 499b5dbb15aSDamon Ding 500b5dbb15aSDamon Ding ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->init_seq); 501b5dbb15aSDamon Ding if (ret) { 502b5dbb15aSDamon Ding printf("failed to parse panel init sequence\n"); 503b5dbb15aSDamon Ding goto free_on_cmds; 504b5dbb15aSDamon Ding } 505b5dbb15aSDamon Ding } 506b5dbb15aSDamon Ding 507b5dbb15aSDamon Ding data = ofnode_get_property(mcu_panel_node, "panel-exit-sequence", &len); 508b5dbb15aSDamon Ding if (data) { 509b5dbb15aSDamon Ding mcu_panel->desc->exit_seq = calloc(1, sizeof(*mcu_panel->desc->exit_seq)); 510b5dbb15aSDamon Ding if (!mcu_panel->desc->exit_seq) { 511b5dbb15aSDamon Ding ret = -ENOMEM; 512b5dbb15aSDamon Ding goto free_on_cmds; 513b5dbb15aSDamon Ding } 514b5dbb15aSDamon Ding 515b5dbb15aSDamon Ding ret = rockchip_mcu_panel_parse_cmds(data, len, mcu_panel->desc->exit_seq); 516b5dbb15aSDamon Ding if (ret) { 517b5dbb15aSDamon Ding printf("failed to parse panel exit sequence\n"); 518b5dbb15aSDamon Ding goto free_cmds; 519b5dbb15aSDamon Ding } 520b5dbb15aSDamon Ding } 521b5dbb15aSDamon Ding 522b5dbb15aSDamon Ding return 0; 523b5dbb15aSDamon Ding 524b5dbb15aSDamon Ding free_cmds: 525b5dbb15aSDamon Ding free(mcu_panel->desc->exit_seq); 526b5dbb15aSDamon Ding free_on_cmds: 527b5dbb15aSDamon Ding free(mcu_panel->desc->init_seq); 528b5dbb15aSDamon Ding return ret; 529b5dbb15aSDamon Ding } 530b5dbb15aSDamon Ding 5319e02a86eSWyon Bi static int rockchip_rgb_probe(struct udevice *dev) 5329e02a86eSWyon Bi { 5336b9c0415SSandy Huang struct rockchip_rgb *rgb = dev_get_priv(dev); 5344ed82c15SDamon Ding const struct rockchip_rgb_data *rgb_data; 535b5dbb15aSDamon Ding ofnode mcu_panel_node; 536b5dbb15aSDamon Ding int phandle; 537b5dbb15aSDamon Ding int ret; 5389e02a86eSWyon Bi 539406bb09aSAndy Yan rgb->data_sync_bypass = dev_read_bool(dev, "rockchip,data-sync-bypass"); 5404ed82c15SDamon Ding rgb_data = (const struct rockchip_rgb_data *)dev_get_driver_data(dev); 5414ed82c15SDamon Ding if (rgb_data) { 5424ed82c15SDamon Ding rgb->funcs = rgb_data->funcs; 5434ed82c15SDamon Ding if (rgb->data_sync_bypass) 5444ed82c15SDamon Ding rgb->max_dclk_rate = rgb_data->mcu_max_dclk_rate; 5454ed82c15SDamon Ding else 5464ed82c15SDamon Ding rgb->max_dclk_rate = rgb_data->rgb_max_dclk_rate; 547*0fd9ded2SDamon Ding rgb->dclk_delayline = rgb_data->dclk_delayline; 5484ed82c15SDamon Ding } 5494ed82c15SDamon Ding rgb->dev = dev; 5504ed82c15SDamon Ding rgb->grf = syscon_get_regmap(dev_get_parent(dev)); 551cb17ca6cSSandy Huang rgb->id = of_alias_get_id(ofnode_to_np(dev->node), "rgb"); 552cb17ca6cSSandy Huang if (rgb->id < 0) 553cb17ca6cSSandy Huang rgb->id = 0; 5549e02a86eSWyon Bi 555b5dbb15aSDamon Ding mcu_panel_node = dev_read_subnode(dev, "mcu-panel"); 556b5dbb15aSDamon Ding if (ofnode_valid(mcu_panel_node) && ofnode_is_available(mcu_panel_node)) { 557b5dbb15aSDamon Ding struct rockchip_mcu_panel *mcu_panel; 558b5dbb15aSDamon Ding 559b5dbb15aSDamon Ding mcu_panel = malloc(sizeof(struct rockchip_mcu_panel)); 560b5dbb15aSDamon Ding if (!mcu_panel) { 561b5dbb15aSDamon Ding printf("failed to alloc mcu_panel data\n"); 562b5dbb15aSDamon Ding return -ENOMEM; 563b5dbb15aSDamon Ding } 564b5dbb15aSDamon Ding 565b5dbb15aSDamon Ding ret = rockchip_mcu_panel_init(mcu_panel, mcu_panel_node); 566b5dbb15aSDamon Ding if (ret < 0) { 567b5dbb15aSDamon Ding printf("failed to init mcu_panel: %d\n", ret); 568b5dbb15aSDamon Ding return ret; 569b5dbb15aSDamon Ding } 570b5dbb15aSDamon Ding 571b5dbb15aSDamon Ding phandle = ofnode_read_u32_default(mcu_panel_node, "backlight", -1); 572b5dbb15aSDamon Ding if (phandle < 0) { 573b5dbb15aSDamon Ding printf("failed to find backlight phandle\n"); 574b5dbb15aSDamon Ding return -EINVAL; 575b5dbb15aSDamon Ding } 576b5dbb15aSDamon Ding 577b5dbb15aSDamon Ding ret = uclass_get_device_by_phandle_id(UCLASS_PANEL_BACKLIGHT, phandle, 578b5dbb15aSDamon Ding &mcu_panel->backlight); 579b5dbb15aSDamon Ding if (ret && ret != -ENOENT) { 580b5dbb15aSDamon Ding printf("%s: failed to get backlight device: %d\n", __func__, ret); 581b5dbb15aSDamon Ding return ret; 582b5dbb15aSDamon Ding } 583b5dbb15aSDamon Ding 584b5dbb15aSDamon Ding mcu_panel->base.dev = dev; 585b5dbb15aSDamon Ding mcu_panel->base.bus_format = mcu_panel->desc->bus_format; 586b5dbb15aSDamon Ding mcu_panel->base.bpc = mcu_panel->desc->bpc; 587b5dbb15aSDamon Ding mcu_panel->base.funcs = &rockchip_mcu_panel_funcs; 588a42af2e5SDamon Ding mcu_panel->enabled = false; 589a42af2e5SDamon Ding mcu_panel->prepared = false; 590b5dbb15aSDamon Ding 591b5dbb15aSDamon Ding rgb->connector.panel = &mcu_panel->base; 592b5dbb15aSDamon Ding } 593b5dbb15aSDamon Ding 5940594ce39SZhang Yubing rockchip_connector_bind(&rgb->connector, dev, rgb->id, &rockchip_rgb_connector_funcs, 5950594ce39SZhang Yubing NULL, DRM_MODE_CONNECTOR_LVDS); 5960594ce39SZhang Yubing 5979e02a86eSWyon Bi return 0; 5989e02a86eSWyon Bi } 5999e02a86eSWyon Bi 600e8dd2b64SDamon Ding static void rv1106_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 601e8dd2b64SDamon Ding { 602e8dd2b64SDamon Ding regmap_write(rgb->grf, RV1106_VENC_GRF_VOP_IO_WRAPPER, 603e8dd2b64SDamon Ding RV1106_IO_BYPASS_SEL(rgb->data_sync_bypass ? 0x3 : 0x0)); 604e8dd2b64SDamon Ding regmap_write(rgb->grf, RV1106_VOGRF_VOP_PIPE_BYPASS, 605e8dd2b64SDamon Ding RV1106_VOP_PIPE_BYPASS(rgb->data_sync_bypass ? 0x3 : 0x0)); 606e8dd2b64SDamon Ding } 607e8dd2b64SDamon Ding 608e8dd2b64SDamon Ding static const struct rockchip_rgb_funcs rv1106_rgb_funcs = { 609e8dd2b64SDamon Ding .prepare = rv1106_rgb_prepare, 610e8dd2b64SDamon Ding }; 611e8dd2b64SDamon Ding 6124ed82c15SDamon Ding static const struct rockchip_rgb_data rv1106_rgb = { 6134ed82c15SDamon Ding .rgb_max_dclk_rate = 74250, 6144ed82c15SDamon Ding .mcu_max_dclk_rate = 150000, 6154ed82c15SDamon Ding .funcs = &rv1106_rgb_funcs, 6164ed82c15SDamon Ding }; 6174ed82c15SDamon Ding 618406bb09aSAndy Yan static void rv1126_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 619406bb09aSAndy Yan { 620406bb09aSAndy Yan regmap_write(rgb->grf, RV1126_GRF_IOFUNC_CON3, 621406bb09aSAndy Yan RV1126_LCDC_IO_BYPASS(rgb->data_sync_bypass)); 622406bb09aSAndy Yan } 623406bb09aSAndy Yan 624406bb09aSAndy Yan static const struct rockchip_rgb_funcs rv1126_rgb_funcs = { 625406bb09aSAndy Yan .prepare = rv1126_rgb_prepare, 626406bb09aSAndy Yan }; 627406bb09aSAndy Yan 6284ed82c15SDamon Ding static const struct rockchip_rgb_data rv1126_rgb = { 6294ed82c15SDamon Ding .funcs = &rv1126_rgb_funcs, 6304ed82c15SDamon Ding }; 6314ed82c15SDamon Ding 6324ec7b4d4SSandy Huang static void px30_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 6336b9c0415SSandy Huang { 634a4878ddaSWyon Bi regmap_write(rgb->grf, PX30_GRF_PD_VO_CON1, PX30_RGB_VOP_SEL(pipe) | 635406bb09aSAndy Yan PX30_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass)); 6366b9c0415SSandy Huang } 6376b9c0415SSandy Huang 6386b9c0415SSandy Huang static const struct rockchip_rgb_funcs px30_rgb_funcs = { 6394ec7b4d4SSandy Huang .prepare = px30_rgb_prepare, 6406b9c0415SSandy Huang }; 6416b9c0415SSandy Huang 6424ed82c15SDamon Ding static const struct rockchip_rgb_data px30_rgb = { 6434ed82c15SDamon Ding .funcs = &px30_rgb_funcs, 6444ed82c15SDamon Ding }; 6454ed82c15SDamon Ding 6464ec7b4d4SSandy Huang static void rk1808_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 6476b9c0415SSandy Huang { 6486b9c0415SSandy Huang regmap_write(rgb->grf, RK1808_GRF_PD_VO_CON1, 649406bb09aSAndy Yan RK1808_RGB_DATA_SYNC_BYPASS(rgb->data_sync_bypass)); 6506b9c0415SSandy Huang } 6516b9c0415SSandy Huang 6526b9c0415SSandy Huang static const struct rockchip_rgb_funcs rk1808_rgb_funcs = { 6534ec7b4d4SSandy Huang .prepare = rk1808_rgb_prepare, 6546b9c0415SSandy Huang }; 6556b9c0415SSandy Huang 6564ed82c15SDamon Ding static const struct rockchip_rgb_data rk1808_rgb = { 6574ed82c15SDamon Ding .funcs = &rk1808_rgb_funcs, 6584ed82c15SDamon Ding }; 6594ed82c15SDamon Ding 6604ec7b4d4SSandy Huang static void rk3288_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 66149627130SWyon Bi { 66249627130SWyon Bi regmap_write(rgb->grf, RK3288_GRF_SOC_CON6, RK3288_LVDS_LCDC_SEL(pipe)); 66349627130SWyon Bi regmap_write(rgb->grf, RK3288_GRF_SOC_CON7, 66449627130SWyon Bi RK3288_LVDS_PWRDWN(0) | RK3288_LVDS_CON_ENABLE_2(1) | 66549627130SWyon Bi RK3288_LVDS_CON_ENABLE_1(1) | RK3288_LVDS_CON_CLKINV(0) | 66649627130SWyon Bi RK3288_LVDS_CON_TTL_EN(1)); 66749627130SWyon Bi } 66849627130SWyon Bi 6694ec7b4d4SSandy Huang static void rk3288_rgb_unprepare(struct rockchip_rgb *rgb) 67049627130SWyon Bi { 67149627130SWyon Bi regmap_write(rgb->grf, RK3288_GRF_SOC_CON7, 67249627130SWyon Bi RK3288_LVDS_PWRDWN(1) | RK3288_LVDS_CON_ENABLE_2(0) | 67349627130SWyon Bi RK3288_LVDS_CON_ENABLE_1(0) | RK3288_LVDS_CON_TTL_EN(0)); 67449627130SWyon Bi } 67549627130SWyon Bi 67649627130SWyon Bi static const struct rockchip_rgb_funcs rk3288_rgb_funcs = { 6774ec7b4d4SSandy Huang .prepare = rk3288_rgb_prepare, 6784ec7b4d4SSandy Huang .unprepare = rk3288_rgb_unprepare, 67949627130SWyon Bi }; 68049627130SWyon Bi 6814ed82c15SDamon Ding static const struct rockchip_rgb_data rk3288_rgb = { 6824ed82c15SDamon Ding .funcs = &rk3288_rgb_funcs, 6834ed82c15SDamon Ding }; 6844ed82c15SDamon Ding 6854ec7b4d4SSandy Huang static void rk3368_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 6866383df2bSSandy Huang { 6876383df2bSSandy Huang regmap_write(rgb->grf, RK3368_GRF_SOC_CON15, RK3368_FORCE_JETAG(0)); 6886383df2bSSandy Huang } 6896383df2bSSandy Huang 6906383df2bSSandy Huang static const struct rockchip_rgb_funcs rk3368_rgb_funcs = { 6914ec7b4d4SSandy Huang .prepare = rk3368_rgb_prepare, 6926383df2bSSandy Huang }; 6936383df2bSSandy Huang 6944ed82c15SDamon Ding static const struct rockchip_rgb_data rk3368_rgb = { 6954ed82c15SDamon Ding .funcs = &rk3368_rgb_funcs, 6964ed82c15SDamon Ding }; 6974ed82c15SDamon Ding 698078f1c2cSDamon Ding static void rk3562_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 699078f1c2cSDamon Ding { 700078f1c2cSDamon Ding regmap_write(rgb->grf, RK3562_GRF_IOC_VO_IO_CON, 701078f1c2cSDamon Ding RK3562_RGB_DATA_BYPASS(rgb->data_sync_bypass)); 702078f1c2cSDamon Ding } 703078f1c2cSDamon Ding 704078f1c2cSDamon Ding static const struct rockchip_rgb_funcs rk3562_rgb_funcs = { 705078f1c2cSDamon Ding .prepare = rk3562_rgb_prepare, 706078f1c2cSDamon Ding }; 707078f1c2cSDamon Ding 7084ed82c15SDamon Ding static const struct rockchip_rgb_data rk3562_rgb = { 7094ed82c15SDamon Ding .funcs = &rk3562_rgb_funcs, 7104ed82c15SDamon Ding }; 7114ed82c15SDamon Ding 712c55d261eSSandy Huang static void rk3568_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 713c55d261eSSandy Huang { 714963b371cSSandy Huang regmap_write(rgb->grf, RK3568_GRF_VO_CON1, RK3568_RGB_DATA_BYPASS(rgb->data_sync_bypass)); 715c55d261eSSandy Huang } 716c55d261eSSandy Huang 717c55d261eSSandy Huang static const struct rockchip_rgb_funcs rk3568_rgb_funcs = { 718c55d261eSSandy Huang .prepare = rk3568_rgb_prepare, 719c55d261eSSandy Huang }; 720c55d261eSSandy Huang 7214ed82c15SDamon Ding static const struct rockchip_rgb_data rk3568_rgb = { 7224ed82c15SDamon Ding .funcs = &rk3568_rgb_funcs, 7234ed82c15SDamon Ding }; 7244ed82c15SDamon Ding 725181a4463SDamon Ding static void rk3576_rgb_prepare(struct rockchip_rgb *rgb, int pipe) 726181a4463SDamon Ding { 727181a4463SDamon Ding regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8, 728181a4463SDamon Ding RK3576_VOP_MCU_SEL(rgb->data_sync_bypass)); 729*0fd9ded2SDamon Ding regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8, 730*0fd9ded2SDamon Ding RK3576_VOP_DLL_SEL(true)); 731*0fd9ded2SDamon Ding regmap_write(rgb->grf, RK3576_VCCIO_IOC_MISC_CON8, 732*0fd9ded2SDamon Ding RK3576_VOP_DCLK_DELAYLINE(rgb->dclk_delayline)); 733181a4463SDamon Ding } 734181a4463SDamon Ding 735181a4463SDamon Ding static const struct rockchip_rgb_funcs rk3576_rgb_funcs = { 736181a4463SDamon Ding .prepare = rk3576_rgb_prepare, 737181a4463SDamon Ding }; 738181a4463SDamon Ding 7394ed82c15SDamon Ding static const struct rockchip_rgb_data rk3576_rgb = { 740*0fd9ded2SDamon Ding .dclk_delayline = 5, 7414ed82c15SDamon Ding .funcs = &rk3576_rgb_funcs, 7424ed82c15SDamon Ding }; 7434ed82c15SDamon Ding 7449e02a86eSWyon Bi static const struct udevice_id rockchip_rgb_ids[] = { 7459e02a86eSWyon Bi { 7469e02a86eSWyon Bi .compatible = "rockchip,px30-rgb", 7474ed82c15SDamon Ding .data = (ulong)&px30_rgb, 7486b9c0415SSandy Huang }, 7496b9c0415SSandy Huang { 7506b9c0415SSandy Huang .compatible = "rockchip,rk1808-rgb", 7514ed82c15SDamon Ding .data = (ulong)&rk1808_rgb, 7529e02a86eSWyon Bi }, 7539e02a86eSWyon Bi { 7549e02a86eSWyon Bi .compatible = "rockchip,rk3066-rgb", 7559e02a86eSWyon Bi }, 7569e02a86eSWyon Bi { 75749627130SWyon Bi .compatible = "rockchip,rk3128-rgb", 75849627130SWyon Bi }, 75949627130SWyon Bi { 76049627130SWyon Bi .compatible = "rockchip,rk3288-rgb", 7614ed82c15SDamon Ding .data = (ulong)&rk3288_rgb, 76249627130SWyon Bi }, 76349627130SWyon Bi { 7649e02a86eSWyon Bi .compatible = "rockchip,rk3308-rgb", 7659e02a86eSWyon Bi }, 7669e02a86eSWyon Bi { 76749627130SWyon Bi .compatible = "rockchip,rk3368-rgb", 7684ed82c15SDamon Ding .data = (ulong)&rk3368_rgb, 76949627130SWyon Bi }, 77049627130SWyon Bi { 771078f1c2cSDamon Ding .compatible = "rockchip,rk3562-rgb", 7724ed82c15SDamon Ding .data = (ulong)&rk3562_rgb, 773078f1c2cSDamon Ding }, 774078f1c2cSDamon Ding { 775c55d261eSSandy Huang .compatible = "rockchip,rk3568-rgb", 7764ed82c15SDamon Ding .data = (ulong)&rk3568_rgb, 777c55d261eSSandy Huang }, 778c55d261eSSandy Huang { 779181a4463SDamon Ding .compatible = "rockchip,rk3576-rgb", 7804ed82c15SDamon Ding .data = (ulong)&rk3576_rgb, 781181a4463SDamon Ding }, 782181a4463SDamon Ding { 7839f3137bcSDamon Ding .compatible = "rockchip,rk3588-rgb", 7849f3137bcSDamon Ding }, 7859f3137bcSDamon Ding { 786e8dd2b64SDamon Ding .compatible = "rockchip,rv1106-rgb", 7874ed82c15SDamon Ding .data = (ulong)&rv1106_rgb, 788e8dd2b64SDamon Ding }, 789e8dd2b64SDamon Ding { 7909e02a86eSWyon Bi .compatible = "rockchip,rv1108-rgb", 7919e02a86eSWyon Bi }, 792406bb09aSAndy Yan { 793406bb09aSAndy Yan .compatible = "rockchip,rv1126-rgb", 7944ed82c15SDamon Ding .data = (ulong)&rv1126_rgb, 795406bb09aSAndy Yan }, 7969e02a86eSWyon Bi {} 7979e02a86eSWyon Bi }; 7989e02a86eSWyon Bi 7999e02a86eSWyon Bi U_BOOT_DRIVER(rockchip_rgb) = { 8009e02a86eSWyon Bi .name = "rockchip_rgb", 8019e02a86eSWyon Bi .id = UCLASS_DISPLAY, 8029e02a86eSWyon Bi .of_match = rockchip_rgb_ids, 8039e02a86eSWyon Bi .probe = rockchip_rgb_probe, 8046b9c0415SSandy Huang .priv_auto_alloc_size = sizeof(struct rockchip_rgb), 8059e02a86eSWyon Bi }; 806