1 /* 2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd 3 * Author: 4 * Mark Yao <mark.yao@rock-chips.com> 5 * Sandy Huang <hjc@rock-chips.com> 6 * 7 * This software is licensed under the terms of the GNU General Public 8 * License version 2, as published by the Free Software Foundation, and 9 * may be copied, distributed, and modified under those terms. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include <drm/drmP.h> 18 #include <drm/drm_atomic_helper.h> 19 #include <drm/drm_crtc_helper.h> 20 #include <drm/drm_dp_helper.h> 21 #include <drm/drm_panel.h> 22 #include <drm/drm_of.h> 23 24 #include <linux/component.h> 25 #include <linux/clk.h> 26 #include <linux/mfd/syscon.h> 27 #include <linux/of_graph.h> 28 #include <linux/pinctrl/devinfo.h> 29 #include <linux/pm_runtime.h> 30 #include <linux/regmap.h> 31 #include <linux/reset.h> 32 33 #include "rockchip_drm_drv.h" 34 #include "rockchip_drm_vop.h" 35 #include "rockchip_lvds.h" 36 37 #define DISPLAY_OUTPUT_RGB 0 38 #define DISPLAY_OUTPUT_LVDS 1 39 #define DISPLAY_OUTPUT_DUAL_LVDS 2 40 41 #define connector_to_lvds(c) \ 42 container_of(c, struct rockchip_lvds, connector) 43 44 #define encoder_to_lvds(c) \ 45 container_of(c, struct rockchip_lvds, encoder) 46 47 /** 48 * rockchip_lvds_soc_data - rockchip lvds Soc private data 49 * @ch1_offset: lvds channel 1 registe offset 50 * grf_soc_con6: general registe offset for LVDS contrl 51 * grf_soc_con7: general registe offset for LVDS contrl 52 * has_vop_sel: to indicate whether need to choose from different VOP. 53 */ 54 struct rockchip_lvds_soc_data { 55 u32 ch1_offset; 56 int grf_soc_con6; 57 int grf_soc_con7; 58 bool has_vop_sel; 59 }; 60 61 struct rockchip_lvds { 62 struct device *dev; 63 void __iomem *regs; 64 struct regmap *grf; 65 struct clk *pclk; 66 const struct rockchip_lvds_soc_data *soc_data; 67 int output; /* rgb lvds or dual lvds output */ 68 int format; /* vesa or jeida format */ 69 struct drm_device *drm_dev; 70 struct drm_panel *panel; 71 struct drm_bridge *bridge; 72 struct drm_connector connector; 73 struct drm_encoder encoder; 74 struct dev_pin_info *pins; 75 }; 76 77 static inline void lvds_writel(struct rockchip_lvds *lvds, u32 offset, u32 val) 78 { 79 writel_relaxed(val, lvds->regs + offset); 80 if (lvds->output == DISPLAY_OUTPUT_LVDS) 81 return; 82 writel_relaxed(val, lvds->regs + offset + lvds->soc_data->ch1_offset); 83 } 84 85 static inline int lvds_name_to_format(const char *s) 86 { 87 if (strncmp(s, "jeida-18", 8) == 0) 88 return LVDS_JEIDA_18; 89 else if (strncmp(s, "jeida-24", 8) == 0) 90 return LVDS_JEIDA_24; 91 else if (strncmp(s, "vesa-24", 7) == 0) 92 return LVDS_VESA_24; 93 94 return -EINVAL; 95 } 96 97 static inline int lvds_name_to_output(const char *s) 98 { 99 if (strncmp(s, "rgb", 3) == 0) 100 return DISPLAY_OUTPUT_RGB; 101 else if (strncmp(s, "lvds", 4) == 0) 102 return DISPLAY_OUTPUT_LVDS; 103 else if (strncmp(s, "duallvds", 8) == 0) 104 return DISPLAY_OUTPUT_DUAL_LVDS; 105 106 return -EINVAL; 107 } 108 109 static int rockchip_lvds_poweron(struct rockchip_lvds *lvds) 110 { 111 int ret; 112 u32 val; 113 114 ret = clk_enable(lvds->pclk); 115 if (ret < 0) { 116 DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret); 117 return ret; 118 } 119 ret = pm_runtime_get_sync(lvds->dev); 120 if (ret < 0) { 121 DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret); 122 clk_disable(lvds->pclk); 123 return ret; 124 } 125 val = RK3288_LVDS_CH0_REG0_LANE4_EN | RK3288_LVDS_CH0_REG0_LANE3_EN | 126 RK3288_LVDS_CH0_REG0_LANE2_EN | RK3288_LVDS_CH0_REG0_LANE1_EN | 127 RK3288_LVDS_CH0_REG0_LANE0_EN; 128 if (lvds->output == DISPLAY_OUTPUT_RGB) { 129 val |= RK3288_LVDS_CH0_REG0_TTL_EN | 130 RK3288_LVDS_CH0_REG0_LANECK_EN; 131 lvds_writel(lvds, RK3288_LVDS_CH0_REG0, val); 132 lvds_writel(lvds, RK3288_LVDS_CH0_REG2, 133 RK3288_LVDS_PLL_FBDIV_REG2(0x46)); 134 lvds_writel(lvds, RK3288_LVDS_CH0_REG4, 135 RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE | 136 RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE | 137 RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE | 138 RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE | 139 RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE | 140 RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE); 141 lvds_writel(lvds, RK3288_LVDS_CH0_REG5, 142 RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA | 143 RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA | 144 RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA | 145 RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA | 146 RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA | 147 RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA); 148 } else { 149 val |= RK3288_LVDS_CH0_REG0_LVDS_EN | 150 RK3288_LVDS_CH0_REG0_LANECK_EN; 151 lvds_writel(lvds, RK3288_LVDS_CH0_REG0, val); 152 lvds_writel(lvds, RK3288_LVDS_CH0_REG1, 153 RK3288_LVDS_CH0_REG1_LANECK_BIAS | 154 RK3288_LVDS_CH0_REG1_LANE4_BIAS | 155 RK3288_LVDS_CH0_REG1_LANE3_BIAS | 156 RK3288_LVDS_CH0_REG1_LANE2_BIAS | 157 RK3288_LVDS_CH0_REG1_LANE1_BIAS | 158 RK3288_LVDS_CH0_REG1_LANE0_BIAS); 159 lvds_writel(lvds, RK3288_LVDS_CH0_REG2, 160 RK3288_LVDS_CH0_REG2_RESERVE_ON | 161 RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE | 162 RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE | 163 RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE | 164 RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE | 165 RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE | 166 RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE | 167 RK3288_LVDS_PLL_FBDIV_REG2(0x46)); 168 lvds_writel(lvds, RK3288_LVDS_CH0_REG4, 0x00); 169 lvds_writel(lvds, RK3288_LVDS_CH0_REG5, 0x00); 170 } 171 lvds_writel(lvds, RK3288_LVDS_CH0_REG3, RK3288_LVDS_PLL_FBDIV_REG3(0x46)); 172 lvds_writel(lvds, RK3288_LVDS_CH0_REGD, RK3288_LVDS_PLL_PREDIV_REGD(0x0a)); 173 lvds_writel(lvds, RK3288_LVDS_CH0_REG20, RK3288_LVDS_CH0_REG20_LSB); 174 175 lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE); 176 lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE); 177 178 return 0; 179 } 180 181 static void rockchip_lvds_poweroff(struct rockchip_lvds *lvds) 182 { 183 int ret; 184 u32 val; 185 186 lvds_writel(lvds, RK3288_LVDS_CFG_REG21, RK3288_LVDS_CFG_REG21_TX_ENABLE); 187 lvds_writel(lvds, RK3288_LVDS_CFG_REGC, RK3288_LVDS_CFG_REGC_PLL_ENABLE); 188 val = LVDS_DUAL | LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN | LVDS_PWRDN; 189 val |= val << 16; 190 ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); 191 if (ret != 0) 192 DRM_DEV_ERROR(lvds->dev, "Could not write to GRF: %d\n", ret); 193 194 pm_runtime_put(lvds->dev); 195 clk_disable(lvds->pclk); 196 } 197 198 static const struct drm_connector_funcs rockchip_lvds_connector_funcs = { 199 .fill_modes = drm_helper_probe_single_connector_modes, 200 .destroy = drm_connector_cleanup, 201 .reset = drm_atomic_helper_connector_reset, 202 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, 203 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, 204 }; 205 206 static int rockchip_lvds_connector_get_modes(struct drm_connector *connector) 207 { 208 struct rockchip_lvds *lvds = connector_to_lvds(connector); 209 struct drm_panel *panel = lvds->panel; 210 211 return drm_panel_get_modes(panel); 212 } 213 214 static const 215 struct drm_connector_helper_funcs rockchip_lvds_connector_helper_funcs = { 216 .get_modes = rockchip_lvds_connector_get_modes, 217 }; 218 219 static void rockchip_lvds_grf_config(struct drm_encoder *encoder, 220 struct drm_display_mode *mode) 221 { 222 struct rockchip_lvds *lvds = encoder_to_lvds(encoder); 223 u8 pin_hsync = (mode->flags & DRM_MODE_FLAG_PHSYNC) ? 1 : 0; 224 u8 pin_dclk = (mode->flags & DRM_MODE_FLAG_PCSYNC) ? 1 : 0; 225 u32 val; 226 int ret; 227 228 /* iomux to LCD data/sync mode */ 229 if (lvds->output == DISPLAY_OUTPUT_RGB) 230 if (lvds->pins && !IS_ERR(lvds->pins->default_state)) 231 pinctrl_select_state(lvds->pins->p, 232 lvds->pins->default_state); 233 val = lvds->format | LVDS_CH0_EN; 234 if (lvds->output == DISPLAY_OUTPUT_RGB) 235 val |= LVDS_TTL_EN | LVDS_CH1_EN; 236 else if (lvds->output == DISPLAY_OUTPUT_DUAL_LVDS) 237 val |= LVDS_DUAL | LVDS_CH1_EN; 238 239 if ((mode->htotal - mode->hsync_start) & 0x01) 240 val |= LVDS_START_PHASE_RST_1; 241 242 val |= (pin_dclk << 8) | (pin_hsync << 9); 243 val |= (0xffff << 16); 244 ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con7, val); 245 if (ret != 0) { 246 DRM_DEV_ERROR(lvds->dev, "Could not write to GRF: %d\n", ret); 247 return; 248 } 249 } 250 251 static int rockchip_lvds_set_vop_source(struct rockchip_lvds *lvds, 252 struct drm_encoder *encoder) 253 { 254 u32 val; 255 int ret; 256 257 if (!lvds->soc_data->has_vop_sel) 258 return 0; 259 260 ret = drm_of_encoder_active_endpoint_id(lvds->dev->of_node, encoder); 261 if (ret < 0) 262 return ret; 263 264 val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16; 265 if (ret) 266 val |= RK3288_LVDS_SOC_CON6_SEL_VOP_LIT; 267 268 ret = regmap_write(lvds->grf, lvds->soc_data->grf_soc_con6, val); 269 if (ret < 0) 270 return ret; 271 272 return 0; 273 } 274 275 static int 276 rockchip_lvds_encoder_atomic_check(struct drm_encoder *encoder, 277 struct drm_crtc_state *crtc_state, 278 struct drm_connector_state *conn_state) 279 { 280 struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state); 281 282 s->output_mode = ROCKCHIP_OUT_MODE_P888; 283 s->output_type = DRM_MODE_CONNECTOR_LVDS; 284 285 return 0; 286 } 287 288 static void rockchip_lvds_encoder_enable(struct drm_encoder *encoder) 289 { 290 struct rockchip_lvds *lvds = encoder_to_lvds(encoder); 291 struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; 292 int ret; 293 294 drm_panel_prepare(lvds->panel); 295 ret = rockchip_lvds_poweron(lvds); 296 if (ret < 0) { 297 DRM_DEV_ERROR(lvds->dev, "failed to power on lvds: %d\n", ret); 298 drm_panel_unprepare(lvds->panel); 299 } 300 rockchip_lvds_grf_config(encoder, mode); 301 rockchip_lvds_set_vop_source(lvds, encoder); 302 drm_panel_enable(lvds->panel); 303 } 304 305 static void rockchip_lvds_encoder_disable(struct drm_encoder *encoder) 306 { 307 struct rockchip_lvds *lvds = encoder_to_lvds(encoder); 308 309 drm_panel_disable(lvds->panel); 310 rockchip_lvds_poweroff(lvds); 311 drm_panel_unprepare(lvds->panel); 312 } 313 314 static const 315 struct drm_encoder_helper_funcs rockchip_lvds_encoder_helper_funcs = { 316 .enable = rockchip_lvds_encoder_enable, 317 .disable = rockchip_lvds_encoder_disable, 318 .atomic_check = rockchip_lvds_encoder_atomic_check, 319 }; 320 321 static const struct drm_encoder_funcs rockchip_lvds_encoder_funcs = { 322 .destroy = drm_encoder_cleanup, 323 }; 324 325 static const struct rockchip_lvds_soc_data rk3288_lvds_data = { 326 .ch1_offset = 0x100, 327 .grf_soc_con6 = 0x025c, 328 .grf_soc_con7 = 0x0260, 329 .has_vop_sel = true, 330 }; 331 332 static const struct of_device_id rockchip_lvds_dt_ids[] = { 333 { 334 .compatible = "rockchip,rk3288-lvds", 335 .data = &rk3288_lvds_data 336 }, 337 {} 338 }; 339 MODULE_DEVICE_TABLE(of, rockchip_lvds_dt_ids); 340 341 static int rockchip_lvds_bind(struct device *dev, struct device *master, 342 void *data) 343 { 344 struct rockchip_lvds *lvds = dev_get_drvdata(dev); 345 struct drm_device *drm_dev = data; 346 struct drm_encoder *encoder; 347 struct drm_connector *connector; 348 struct device_node *remote = NULL; 349 struct device_node *port, *endpoint; 350 int ret = 0, child_count = 0; 351 const char *name; 352 u32 endpoint_id; 353 354 lvds->drm_dev = drm_dev; 355 port = of_graph_get_port_by_id(dev->of_node, 1); 356 if (!port) { 357 DRM_DEV_ERROR(dev, 358 "can't found port point, please init lvds panel port!\n"); 359 return -EINVAL; 360 } 361 for_each_child_of_node(port, endpoint) { 362 child_count++; 363 of_property_read_u32(endpoint, "reg", &endpoint_id); 364 ret = drm_of_find_panel_or_bridge(dev->of_node, 1, endpoint_id, 365 &lvds->panel, &lvds->bridge); 366 if (!ret) 367 break; 368 } 369 if (!child_count) { 370 DRM_DEV_ERROR(dev, "lvds port does not have any children\n"); 371 ret = -EINVAL; 372 goto err_put_port; 373 } else if (ret) { 374 DRM_DEV_ERROR(dev, "failed to find panel and bridge node\n"); 375 ret = -EPROBE_DEFER; 376 goto err_put_port; 377 } 378 if (lvds->panel) 379 remote = lvds->panel->dev->of_node; 380 else 381 remote = lvds->bridge->of_node; 382 if (of_property_read_string(dev->of_node, "rockchip,output", &name)) 383 /* default set it as output rgb */ 384 lvds->output = DISPLAY_OUTPUT_RGB; 385 else 386 lvds->output = lvds_name_to_output(name); 387 388 if (lvds->output < 0) { 389 DRM_DEV_ERROR(dev, "invalid output type [%s]\n", name); 390 ret = lvds->output; 391 goto err_put_remote; 392 } 393 394 if (of_property_read_string(remote, "data-mapping", &name)) 395 /* default set it as format vesa 18 */ 396 lvds->format = LVDS_VESA_18; 397 else 398 lvds->format = lvds_name_to_format(name); 399 400 if (lvds->format < 0) { 401 DRM_DEV_ERROR(dev, "invalid data-mapping format [%s]\n", name); 402 ret = lvds->format; 403 goto err_put_remote; 404 } 405 406 encoder = &lvds->encoder; 407 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm_dev, 408 dev->of_node); 409 410 ret = drm_encoder_init(drm_dev, encoder, &rockchip_lvds_encoder_funcs, 411 DRM_MODE_ENCODER_LVDS, NULL); 412 if (ret < 0) { 413 DRM_DEV_ERROR(drm_dev->dev, 414 "failed to initialize encoder: %d\n", ret); 415 goto err_put_remote; 416 } 417 418 drm_encoder_helper_add(encoder, &rockchip_lvds_encoder_helper_funcs); 419 420 if (lvds->panel) { 421 connector = &lvds->connector; 422 connector->dpms = DRM_MODE_DPMS_OFF; 423 ret = drm_connector_init(drm_dev, connector, 424 &rockchip_lvds_connector_funcs, 425 DRM_MODE_CONNECTOR_LVDS); 426 if (ret < 0) { 427 DRM_DEV_ERROR(drm_dev->dev, 428 "failed to initialize connector: %d\n", ret); 429 goto err_free_encoder; 430 } 431 432 drm_connector_helper_add(connector, 433 &rockchip_lvds_connector_helper_funcs); 434 435 ret = drm_mode_connector_attach_encoder(connector, encoder); 436 if (ret < 0) { 437 DRM_DEV_ERROR(drm_dev->dev, 438 "failed to attach encoder: %d\n", ret); 439 goto err_free_connector; 440 } 441 442 ret = drm_panel_attach(lvds->panel, connector); 443 if (ret < 0) { 444 DRM_DEV_ERROR(drm_dev->dev, 445 "failed to attach panel: %d\n", ret); 446 goto err_free_connector; 447 } 448 } else { 449 lvds->bridge->encoder = encoder; 450 ret = drm_bridge_attach(encoder, lvds->bridge, NULL); 451 if (ret) { 452 DRM_DEV_ERROR(drm_dev->dev, 453 "failed to attach bridge: %d\n", ret); 454 goto err_free_encoder; 455 } 456 encoder->bridge = lvds->bridge; 457 } 458 459 pm_runtime_enable(dev); 460 of_node_put(remote); 461 of_node_put(port); 462 463 return 0; 464 465 err_free_connector: 466 drm_connector_cleanup(connector); 467 err_free_encoder: 468 drm_encoder_cleanup(encoder); 469 err_put_remote: 470 of_node_put(remote); 471 err_put_port: 472 of_node_put(port); 473 474 return ret; 475 } 476 477 static void rockchip_lvds_unbind(struct device *dev, struct device *master, 478 void *data) 479 { 480 struct rockchip_lvds *lvds = dev_get_drvdata(dev); 481 482 rockchip_lvds_encoder_disable(&lvds->encoder); 483 if (lvds->panel) 484 drm_panel_detach(lvds->panel); 485 pm_runtime_disable(dev); 486 drm_connector_cleanup(&lvds->connector); 487 drm_encoder_cleanup(&lvds->encoder); 488 } 489 490 static const struct component_ops rockchip_lvds_component_ops = { 491 .bind = rockchip_lvds_bind, 492 .unbind = rockchip_lvds_unbind, 493 }; 494 495 static int rockchip_lvds_probe(struct platform_device *pdev) 496 { 497 struct device *dev = &pdev->dev; 498 struct rockchip_lvds *lvds; 499 const struct of_device_id *match; 500 struct resource *res; 501 int ret; 502 503 if (!dev->of_node) 504 return -ENODEV; 505 506 lvds = devm_kzalloc(&pdev->dev, sizeof(*lvds), GFP_KERNEL); 507 if (!lvds) 508 return -ENOMEM; 509 510 lvds->dev = dev; 511 match = of_match_node(rockchip_lvds_dt_ids, dev->of_node); 512 if (!match) 513 return -ENODEV; 514 lvds->soc_data = match->data; 515 516 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 517 lvds->regs = devm_ioremap_resource(&pdev->dev, res); 518 if (IS_ERR(lvds->regs)) 519 return PTR_ERR(lvds->regs); 520 521 lvds->pclk = devm_clk_get(&pdev->dev, "pclk_lvds"); 522 if (IS_ERR(lvds->pclk)) { 523 DRM_DEV_ERROR(dev, "could not get pclk_lvds\n"); 524 return PTR_ERR(lvds->pclk); 525 } 526 527 lvds->pins = devm_kzalloc(lvds->dev, sizeof(*lvds->pins), 528 GFP_KERNEL); 529 if (!lvds->pins) 530 return -ENOMEM; 531 532 lvds->pins->p = devm_pinctrl_get(lvds->dev); 533 if (IS_ERR(lvds->pins->p)) { 534 DRM_DEV_ERROR(dev, "no pinctrl handle\n"); 535 devm_kfree(lvds->dev, lvds->pins); 536 lvds->pins = NULL; 537 } else { 538 lvds->pins->default_state = 539 pinctrl_lookup_state(lvds->pins->p, "lcdc"); 540 if (IS_ERR(lvds->pins->default_state)) { 541 DRM_DEV_ERROR(dev, "no default pinctrl state\n"); 542 devm_kfree(lvds->dev, lvds->pins); 543 lvds->pins = NULL; 544 } 545 } 546 547 lvds->grf = syscon_regmap_lookup_by_phandle(dev->of_node, 548 "rockchip,grf"); 549 if (IS_ERR(lvds->grf)) { 550 DRM_DEV_ERROR(dev, "missing rockchip,grf property\n"); 551 return PTR_ERR(lvds->grf); 552 } 553 554 dev_set_drvdata(dev, lvds); 555 556 ret = clk_prepare(lvds->pclk); 557 if (ret < 0) { 558 DRM_DEV_ERROR(dev, "failed to prepare pclk_lvds\n"); 559 return ret; 560 } 561 ret = component_add(&pdev->dev, &rockchip_lvds_component_ops); 562 if (ret < 0) { 563 DRM_DEV_ERROR(dev, "failed to add component\n"); 564 clk_unprepare(lvds->pclk); 565 } 566 567 return ret; 568 } 569 570 static int rockchip_lvds_remove(struct platform_device *pdev) 571 { 572 struct rockchip_lvds *lvds = dev_get_drvdata(&pdev->dev); 573 574 component_del(&pdev->dev, &rockchip_lvds_component_ops); 575 clk_unprepare(lvds->pclk); 576 577 return 0; 578 } 579 580 struct platform_driver rockchip_lvds_driver = { 581 .probe = rockchip_lvds_probe, 582 .remove = rockchip_lvds_remove, 583 .driver = { 584 .name = "rockchip-lvds", 585 .of_match_table = of_match_ptr(rockchip_lvds_dt_ids), 586 }, 587 }; 588