1/* 2 * i.MX drm driver - LVDS display bridge 3 * 4 * Copyright (C) 2012 Sascha Hauer, Pengutronix 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 18 * MA 02110-1301, USA. 19 */ 20 21#include <linux/module.h> 22#include <linux/clk.h> 23#include <linux/component.h> 24#include <drm/drmP.h> 25#include <drm/drm_fb_helper.h> 26#include <drm/drm_crtc_helper.h> 27#include <linux/mfd/syscon.h> 28#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 29#include <linux/of_address.h> 30#include <linux/of_device.h> 31#include <video/of_videomode.h> 32#include <linux/regmap.h> 33#include <linux/videodev2.h> 34 35#include "imx-drm.h" 36 37#define DRIVER_NAME "imx-ldb" 38 39#define LDB_CH0_MODE_EN_TO_DI0 (1 << 0) 40#define LDB_CH0_MODE_EN_TO_DI1 (3 << 0) 41#define LDB_CH0_MODE_EN_MASK (3 << 0) 42#define LDB_CH1_MODE_EN_TO_DI0 (1 << 2) 43#define LDB_CH1_MODE_EN_TO_DI1 (3 << 2) 44#define LDB_CH1_MODE_EN_MASK (3 << 2) 45#define LDB_SPLIT_MODE_EN (1 << 4) 46#define LDB_DATA_WIDTH_CH0_24 (1 << 5) 47#define LDB_BIT_MAP_CH0_JEIDA (1 << 6) 48#define LDB_DATA_WIDTH_CH1_24 (1 << 7) 49#define LDB_BIT_MAP_CH1_JEIDA (1 << 8) 50#define LDB_DI0_VS_POL_ACT_LOW (1 << 9) 51#define LDB_DI1_VS_POL_ACT_LOW (1 << 10) 52#define LDB_BGREF_RMODE_INT (1 << 15) 53 54#define con_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, connector) 55#define enc_to_imx_ldb_ch(x) container_of(x, struct imx_ldb_channel, encoder) 56 57struct imx_ldb; 58 59struct imx_ldb_channel { 60 struct imx_ldb *ldb; 61 struct drm_connector connector; 62 struct drm_encoder encoder; 63 struct device_node *child; 64 int chno; 65 void *edid; 66 int edid_len; 67 struct drm_display_mode mode; 68 int mode_valid; 69}; 70 71struct bus_mux { 72 int reg; 73 int shift; 74 int mask; 75}; 76 77struct imx_ldb { 78 struct regmap *regmap; 79 struct device *dev; 80 struct imx_ldb_channel channel[2]; 81 struct clk *clk[2]; /* our own clock */ 82 struct clk *clk_sel[4]; /* parent of display clock */ 83 struct clk *clk_pll[2]; /* upstream clock we can adjust */ 84 u32 ldb_ctrl; 85 const struct bus_mux *lvds_mux; 86}; 87 88static enum drm_connector_status imx_ldb_connector_detect( 89 struct drm_connector *connector, bool force) 90{ 91 return connector_status_connected; 92} 93 94static int imx_ldb_connector_get_modes(struct drm_connector *connector) 95{ 96 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); 97 int num_modes = 0; 98 99 if (imx_ldb_ch->edid) { 100 drm_mode_connector_update_edid_property(connector, 101 imx_ldb_ch->edid); 102 num_modes = drm_add_edid_modes(connector, imx_ldb_ch->edid); 103 } 104 105 if (imx_ldb_ch->mode_valid) { 106 struct drm_display_mode *mode; 107 108 mode = drm_mode_create(connector->dev); 109 if (!mode) 110 return -EINVAL; 111 drm_mode_copy(mode, &imx_ldb_ch->mode); 112 mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 113 drm_mode_probed_add(connector, mode); 114 num_modes++; 115 } 116 117 return num_modes; 118} 119 120static struct drm_encoder *imx_ldb_connector_best_encoder( 121 struct drm_connector *connector) 122{ 123 struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); 124 125 return &imx_ldb_ch->encoder; 126} 127 128static void imx_ldb_encoder_dpms(struct drm_encoder *encoder, int mode) 129{ 130} 131 132static bool imx_ldb_encoder_mode_fixup(struct drm_encoder *encoder, 133 const struct drm_display_mode *mode, 134 struct drm_display_mode *adjusted_mode) 135{ 136 return true; 137} 138 139static void imx_ldb_set_clock(struct imx_ldb *ldb, int mux, int chno, 140 unsigned long serial_clk, unsigned long di_clk) 141{ 142 int ret; 143 144 dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__, 145 clk_get_rate(ldb->clk_pll[chno]), serial_clk); 146 clk_set_rate(ldb->clk_pll[chno], serial_clk); 147 148 dev_dbg(ldb->dev, "%s after: %ld\n", __func__, 149 clk_get_rate(ldb->clk_pll[chno])); 150 151 dev_dbg(ldb->dev, "%s: now: %ld want: %ld\n", __func__, 152 clk_get_rate(ldb->clk[chno]), 153 (long int)di_clk); 154 clk_set_rate(ldb->clk[chno], di_clk); 155 156 dev_dbg(ldb->dev, "%s after: %ld\n", __func__, 157 clk_get_rate(ldb->clk[chno])); 158 159 /* set display clock mux to LDB input clock */ 160 ret = clk_set_parent(ldb->clk_sel[mux], ldb->clk[chno]); 161 if (ret) 162 dev_err(ldb->dev, 163 "unable to set di%d parent clock to ldb_di%d\n", mux, 164 chno); 165} 166 167static void imx_ldb_encoder_prepare(struct drm_encoder *encoder) 168{ 169 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 170 struct imx_ldb *ldb = imx_ldb_ch->ldb; 171 struct drm_display_mode *mode = &encoder->crtc->mode; 172 u32 pixel_fmt; 173 unsigned long serial_clk; 174 unsigned long di_clk = mode->clock * 1000; 175 int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder); 176 177 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) { 178 /* dual channel LVDS mode */ 179 serial_clk = 3500UL * mode->clock; 180 imx_ldb_set_clock(ldb, mux, 0, serial_clk, di_clk); 181 imx_ldb_set_clock(ldb, mux, 1, serial_clk, di_clk); 182 } else { 183 serial_clk = 7000UL * mode->clock; 184 imx_ldb_set_clock(ldb, mux, imx_ldb_ch->chno, serial_clk, 185 di_clk); 186 } 187 188 switch (imx_ldb_ch->chno) { 189 case 0: 190 pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH0_24) ? 191 V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666; 192 break; 193 case 1: 194 pixel_fmt = (ldb->ldb_ctrl & LDB_DATA_WIDTH_CH1_24) ? 195 V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666; 196 break; 197 default: 198 dev_err(ldb->dev, "unable to config di%d panel format\n", 199 imx_ldb_ch->chno); 200 pixel_fmt = V4L2_PIX_FMT_RGB24; 201 } 202 203 imx_drm_panel_format(encoder, pixel_fmt); 204} 205 206static void imx_ldb_encoder_commit(struct drm_encoder *encoder) 207{ 208 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 209 struct imx_ldb *ldb = imx_ldb_ch->ldb; 210 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; 211 int mux = imx_drm_encoder_get_mux_id(imx_ldb_ch->child, encoder); 212 213 if (dual) { 214 clk_prepare_enable(ldb->clk[0]); 215 clk_prepare_enable(ldb->clk[1]); 216 } 217 218 if (imx_ldb_ch == &ldb->channel[0] || dual) { 219 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; 220 if (mux == 0 || ldb->lvds_mux) 221 ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0; 222 else if (mux == 1) 223 ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI1; 224 } 225 if (imx_ldb_ch == &ldb->channel[1] || dual) { 226 ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; 227 if (mux == 1 || ldb->lvds_mux) 228 ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI1; 229 else if (mux == 0) 230 ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI0; 231 } 232 233 if (ldb->lvds_mux) { 234 const struct bus_mux *lvds_mux = NULL; 235 236 if (imx_ldb_ch == &ldb->channel[0]) 237 lvds_mux = &ldb->lvds_mux[0]; 238 else if (imx_ldb_ch == &ldb->channel[1]) 239 lvds_mux = &ldb->lvds_mux[1]; 240 241 regmap_update_bits(ldb->regmap, lvds_mux->reg, lvds_mux->mask, 242 mux << lvds_mux->shift); 243 } 244 245 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl); 246} 247 248static void imx_ldb_encoder_mode_set(struct drm_encoder *encoder, 249 struct drm_display_mode *mode, 250 struct drm_display_mode *adjusted_mode) 251{ 252 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 253 struct imx_ldb *ldb = imx_ldb_ch->ldb; 254 int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; 255 256 if (mode->clock > 170000) { 257 dev_warn(ldb->dev, 258 "%s: mode exceeds 170 MHz pixel clock\n", __func__); 259 } 260 if (mode->clock > 85000 && !dual) { 261 dev_warn(ldb->dev, 262 "%s: mode exceeds 85 MHz pixel clock\n", __func__); 263 } 264 265 /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */ 266 if (imx_ldb_ch == &ldb->channel[0]) { 267 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 268 ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW; 269 else if (mode->flags & DRM_MODE_FLAG_PVSYNC) 270 ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW; 271 } 272 if (imx_ldb_ch == &ldb->channel[1]) { 273 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 274 ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW; 275 else if (mode->flags & DRM_MODE_FLAG_PVSYNC) 276 ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW; 277 } 278} 279 280static void imx_ldb_encoder_disable(struct drm_encoder *encoder) 281{ 282 struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); 283 struct imx_ldb *ldb = imx_ldb_ch->ldb; 284 285 /* 286 * imx_ldb_encoder_disable is called by 287 * drm_helper_disable_unused_functions without 288 * the encoder being enabled before. 289 */ 290 if (imx_ldb_ch == &ldb->channel[0] && 291 (ldb->ldb_ctrl & LDB_CH0_MODE_EN_MASK) == 0) 292 return; 293 else if (imx_ldb_ch == &ldb->channel[1] && 294 (ldb->ldb_ctrl & LDB_CH1_MODE_EN_MASK) == 0) 295 return; 296 297 if (imx_ldb_ch == &ldb->channel[0]) 298 ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; 299 else if (imx_ldb_ch == &ldb->channel[1]) 300 ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; 301 302 regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl); 303 304 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) { 305 clk_disable_unprepare(ldb->clk[0]); 306 clk_disable_unprepare(ldb->clk[1]); 307 } 308} 309 310static struct drm_connector_funcs imx_ldb_connector_funcs = { 311 .dpms = drm_helper_connector_dpms, 312 .fill_modes = drm_helper_probe_single_connector_modes, 313 .detect = imx_ldb_connector_detect, 314 .destroy = imx_drm_connector_destroy, 315}; 316 317static struct drm_connector_helper_funcs imx_ldb_connector_helper_funcs = { 318 .get_modes = imx_ldb_connector_get_modes, 319 .best_encoder = imx_ldb_connector_best_encoder, 320}; 321 322static struct drm_encoder_funcs imx_ldb_encoder_funcs = { 323 .destroy = imx_drm_encoder_destroy, 324}; 325 326static struct drm_encoder_helper_funcs imx_ldb_encoder_helper_funcs = { 327 .dpms = imx_ldb_encoder_dpms, 328 .mode_fixup = imx_ldb_encoder_mode_fixup, 329 .prepare = imx_ldb_encoder_prepare, 330 .commit = imx_ldb_encoder_commit, 331 .mode_set = imx_ldb_encoder_mode_set, 332 .disable = imx_ldb_encoder_disable, 333}; 334 335static int imx_ldb_get_clk(struct imx_ldb *ldb, int chno) 336{ 337 char clkname[16]; 338 339 snprintf(clkname, sizeof(clkname), "di%d", chno); 340 ldb->clk[chno] = devm_clk_get(ldb->dev, clkname); 341 if (IS_ERR(ldb->clk[chno])) 342 return PTR_ERR(ldb->clk[chno]); 343 344 snprintf(clkname, sizeof(clkname), "di%d_pll", chno); 345 ldb->clk_pll[chno] = devm_clk_get(ldb->dev, clkname); 346 347 return PTR_ERR_OR_ZERO(ldb->clk_pll[chno]); 348} 349 350static int imx_ldb_register(struct drm_device *drm, 351 struct imx_ldb_channel *imx_ldb_ch) 352{ 353 struct imx_ldb *ldb = imx_ldb_ch->ldb; 354 int ret; 355 356 ret = imx_drm_encoder_parse_of(drm, &imx_ldb_ch->encoder, 357 imx_ldb_ch->child); 358 if (ret) 359 return ret; 360 361 ret = imx_ldb_get_clk(ldb, imx_ldb_ch->chno); 362 if (ret) 363 return ret; 364 365 if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) { 366 ret = imx_ldb_get_clk(ldb, 1); 367 if (ret) 368 return ret; 369 } 370 371 drm_encoder_helper_add(&imx_ldb_ch->encoder, 372 &imx_ldb_encoder_helper_funcs); 373 drm_encoder_init(drm, &imx_ldb_ch->encoder, &imx_ldb_encoder_funcs, 374 DRM_MODE_ENCODER_LVDS); 375 376 drm_connector_helper_add(&imx_ldb_ch->connector, 377 &imx_ldb_connector_helper_funcs); 378 drm_connector_init(drm, &imx_ldb_ch->connector, 379 &imx_ldb_connector_funcs, DRM_MODE_CONNECTOR_LVDS); 380 381 drm_mode_connector_attach_encoder(&imx_ldb_ch->connector, 382 &imx_ldb_ch->encoder); 383 384 return 0; 385} 386 387enum { 388 LVDS_BIT_MAP_SPWG, 389 LVDS_BIT_MAP_JEIDA 390}; 391 392static const char * const imx_ldb_bit_mappings[] = { 393 [LVDS_BIT_MAP_SPWG] = "spwg", 394 [LVDS_BIT_MAP_JEIDA] = "jeida", 395}; 396 397static const int of_get_data_mapping(struct device_node *np) 398{ 399 const char *bm; 400 int ret, i; 401 402 ret = of_property_read_string(np, "fsl,data-mapping", &bm); 403 if (ret < 0) 404 return ret; 405 406 for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++) 407 if (!strcasecmp(bm, imx_ldb_bit_mappings[i])) 408 return i; 409 410 return -EINVAL; 411} 412 413static struct bus_mux imx6q_lvds_mux[2] = { 414 { 415 .reg = IOMUXC_GPR3, 416 .shift = 6, 417 .mask = IMX6Q_GPR3_LVDS0_MUX_CTL_MASK, 418 }, { 419 .reg = IOMUXC_GPR3, 420 .shift = 8, 421 .mask = IMX6Q_GPR3_LVDS1_MUX_CTL_MASK, 422 } 423}; 424 425/* 426 * For a device declaring compatible = "fsl,imx6q-ldb", "fsl,imx53-ldb", 427 * of_match_device will walk through this list and take the first entry 428 * matching any of its compatible values. Therefore, the more generic 429 * entries (in this case fsl,imx53-ldb) need to be ordered last. 430 */ 431static const struct of_device_id imx_ldb_dt_ids[] = { 432 { .compatible = "fsl,imx6q-ldb", .data = imx6q_lvds_mux, }, 433 { .compatible = "fsl,imx53-ldb", .data = NULL, }, 434 { } 435}; 436MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids); 437 438static int imx_ldb_bind(struct device *dev, struct device *master, void *data) 439{ 440 struct drm_device *drm = data; 441 struct device_node *np = dev->of_node; 442 const struct of_device_id *of_id = 443 of_match_device(imx_ldb_dt_ids, dev); 444 struct device_node *child; 445 const u8 *edidp; 446 struct imx_ldb *imx_ldb; 447 int datawidth; 448 int mapping; 449 int dual; 450 int ret; 451 int i; 452 453 imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL); 454 if (!imx_ldb) 455 return -ENOMEM; 456 457 imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr"); 458 if (IS_ERR(imx_ldb->regmap)) { 459 dev_err(dev, "failed to get parent regmap\n"); 460 return PTR_ERR(imx_ldb->regmap); 461 } 462 463 imx_ldb->dev = dev; 464 465 if (of_id) 466 imx_ldb->lvds_mux = of_id->data; 467 468 dual = of_property_read_bool(np, "fsl,dual-channel"); 469 if (dual) 470 imx_ldb->ldb_ctrl |= LDB_SPLIT_MODE_EN; 471 472 /* 473 * There are three different possible clock mux configurations: 474 * i.MX53: ipu1_di0_sel, ipu1_di1_sel 475 * i.MX6q: ipu1_di0_sel, ipu1_di1_sel, ipu2_di0_sel, ipu2_di1_sel 476 * i.MX6dl: ipu1_di0_sel, ipu1_di1_sel, lcdif_sel 477 * Map them all to di0_sel...di3_sel. 478 */ 479 for (i = 0; i < 4; i++) { 480 char clkname[16]; 481 482 sprintf(clkname, "di%d_sel", i); 483 imx_ldb->clk_sel[i] = devm_clk_get(imx_ldb->dev, clkname); 484 if (IS_ERR(imx_ldb->clk_sel[i])) { 485 ret = PTR_ERR(imx_ldb->clk_sel[i]); 486 imx_ldb->clk_sel[i] = NULL; 487 break; 488 } 489 } 490 if (i == 0) 491 return ret; 492 493 for_each_child_of_node(np, child) { 494 struct imx_ldb_channel *channel; 495 496 ret = of_property_read_u32(child, "reg", &i); 497 if (ret || i < 0 || i > 1) 498 return -EINVAL; 499 500 if (dual && i > 0) { 501 dev_warn(dev, "dual-channel mode, ignoring second output\n"); 502 continue; 503 } 504 505 if (!of_device_is_available(child)) 506 continue; 507 508 channel = &imx_ldb->channel[i]; 509 channel->ldb = imx_ldb; 510 channel->chno = i; 511 channel->child = child; 512 513 edidp = of_get_property(child, "edid", &channel->edid_len); 514 if (edidp) { 515 channel->edid = kmemdup(edidp, channel->edid_len, 516 GFP_KERNEL); 517 } else { 518 ret = of_get_drm_display_mode(child, &channel->mode, 0); 519 if (!ret) 520 channel->mode_valid = 1; 521 } 522 523 ret = of_property_read_u32(child, "fsl,data-width", &datawidth); 524 if (ret) 525 datawidth = 0; 526 else if (datawidth != 18 && datawidth != 24) 527 return -EINVAL; 528 529 mapping = of_get_data_mapping(child); 530 switch (mapping) { 531 case LVDS_BIT_MAP_SPWG: 532 if (datawidth == 24) { 533 if (i == 0 || dual) 534 imx_ldb->ldb_ctrl |= 535 LDB_DATA_WIDTH_CH0_24; 536 if (i == 1 || dual) 537 imx_ldb->ldb_ctrl |= 538 LDB_DATA_WIDTH_CH1_24; 539 } 540 break; 541 case LVDS_BIT_MAP_JEIDA: 542 if (datawidth == 18) { 543 dev_err(dev, "JEIDA standard only supported in 24 bit\n"); 544 return -EINVAL; 545 } 546 if (i == 0 || dual) 547 imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | 548 LDB_BIT_MAP_CH0_JEIDA; 549 if (i == 1 || dual) 550 imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | 551 LDB_BIT_MAP_CH1_JEIDA; 552 break; 553 default: 554 dev_err(dev, "data mapping not specified or invalid\n"); 555 return -EINVAL; 556 } 557 558 ret = imx_ldb_register(drm, channel); 559 if (ret) 560 return ret; 561 } 562 563 dev_set_drvdata(dev, imx_ldb); 564 565 return 0; 566} 567 568static void imx_ldb_unbind(struct device *dev, struct device *master, 569 void *data) 570{ 571 struct imx_ldb *imx_ldb = dev_get_drvdata(dev); 572 int i; 573 574 for (i = 0; i < 2; i++) { 575 struct imx_ldb_channel *channel = &imx_ldb->channel[i]; 576 577 if (!channel->connector.funcs) 578 continue; 579 580 channel->connector.funcs->destroy(&channel->connector); 581 channel->encoder.funcs->destroy(&channel->encoder); 582 } 583} 584 585static const struct component_ops imx_ldb_ops = { 586 .bind = imx_ldb_bind, 587 .unbind = imx_ldb_unbind, 588}; 589 590static int imx_ldb_probe(struct platform_device *pdev) 591{ 592 return component_add(&pdev->dev, &imx_ldb_ops); 593} 594 595static int imx_ldb_remove(struct platform_device *pdev) 596{ 597 component_del(&pdev->dev, &imx_ldb_ops); 598 return 0; 599} 600 601static struct platform_driver imx_ldb_driver = { 602 .probe = imx_ldb_probe, 603 .remove = imx_ldb_remove, 604 .driver = { 605 .of_match_table = imx_ldb_dt_ids, 606 .name = DRIVER_NAME, 607 .owner = THIS_MODULE, 608 }, 609}; 610 611module_platform_driver(imx_ldb_driver); 612 613MODULE_DESCRIPTION("i.MX LVDS driver"); 614MODULE_AUTHOR("Sascha Hauer, Pengutronix"); 615MODULE_LICENSE("GPL"); 616MODULE_ALIAS("platform:" DRIVER_NAME); 617