1/* 2 * Copyright (C) 2010 Juergen Beisert, Pengutronix 3 * 4 * This code is based on: 5 * Author: Vitaly Wool <vital@embeddedalley.com> 6 * 7 * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved. 8 * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 2 13 * of the License, or (at your option) any later version. 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 */ 19 20#define DRIVER_NAME "mxsfb" 21 22/** 23 * @file 24 * @brief LCDIF driver for i.MX23 and i.MX28 25 * 26 * The LCDIF support four modes of operation 27 * - MPU interface (to drive smart displays) -> not supported yet 28 * - VSYNC interface (like MPU interface plus Vsync) -> not supported yet 29 * - Dotclock interface (to drive LC displays with RGB data and sync signals) 30 * - DVI (to drive ITU-R BT656) -> not supported yet 31 * 32 * This driver depends on a correct setup of the pins used for this purpose 33 * (platform specific). 34 * 35 * For the developer: Don't forget to set the data bus width to the display 36 * in the imx_fb_videomode structure. You will else end up with ugly colours. 37 * If you fight against jitter you can vary the clock delay. This is a feature 38 * of the i.MX28 and you can vary it between 2 ns ... 8 ns in 2 ns steps. Give 39 * the required value in the imx_fb_videomode structure. 40 */ 41 42#include <linux/module.h> 43#include <linux/kernel.h> 44#include <linux/of_device.h> 45#include <linux/platform_device.h> 46#include <linux/clk.h> 47#include <linux/dma-mapping.h> 48#include <linux/io.h> 49#include <linux/fb.h> 50#include <linux/regulator/consumer.h> 51#include <video/of_display_timing.h> 52#include <video/of_videomode.h> 53#include <video/videomode.h> 54 55#define REG_SET 4 56#define REG_CLR 8 57 58#define LCDC_CTRL 0x00 59#define LCDC_CTRL1 0x10 60#define LCDC_V4_CTRL2 0x20 61#define LCDC_V3_TRANSFER_COUNT 0x20 62#define LCDC_V4_TRANSFER_COUNT 0x30 63#define LCDC_V4_CUR_BUF 0x40 64#define LCDC_V4_NEXT_BUF 0x50 65#define LCDC_V3_CUR_BUF 0x30 66#define LCDC_V3_NEXT_BUF 0x40 67#define LCDC_TIMING 0x60 68#define LCDC_VDCTRL0 0x70 69#define LCDC_VDCTRL1 0x80 70#define LCDC_VDCTRL2 0x90 71#define LCDC_VDCTRL3 0xa0 72#define LCDC_VDCTRL4 0xb0 73#define LCDC_DVICTRL0 0xc0 74#define LCDC_DVICTRL1 0xd0 75#define LCDC_DVICTRL2 0xe0 76#define LCDC_DVICTRL3 0xf0 77#define LCDC_DVICTRL4 0x100 78#define LCDC_V4_DATA 0x180 79#define LCDC_V3_DATA 0x1b0 80#define LCDC_V4_DEBUG0 0x1d0 81#define LCDC_V3_DEBUG0 0x1f0 82 83#define CTRL_SFTRST (1 << 31) 84#define CTRL_CLKGATE (1 << 30) 85#define CTRL_BYPASS_COUNT (1 << 19) 86#define CTRL_VSYNC_MODE (1 << 18) 87#define CTRL_DOTCLK_MODE (1 << 17) 88#define CTRL_DATA_SELECT (1 << 16) 89#define CTRL_SET_BUS_WIDTH(x) (((x) & 0x3) << 10) 90#define CTRL_GET_BUS_WIDTH(x) (((x) >> 10) & 0x3) 91#define CTRL_SET_WORD_LENGTH(x) (((x) & 0x3) << 8) 92#define CTRL_GET_WORD_LENGTH(x) (((x) >> 8) & 0x3) 93#define CTRL_MASTER (1 << 5) 94#define CTRL_DF16 (1 << 3) 95#define CTRL_DF18 (1 << 2) 96#define CTRL_DF24 (1 << 1) 97#define CTRL_RUN (1 << 0) 98 99#define CTRL1_FIFO_CLEAR (1 << 21) 100#define CTRL1_SET_BYTE_PACKAGING(x) (((x) & 0xf) << 16) 101#define CTRL1_GET_BYTE_PACKAGING(x) (((x) >> 16) & 0xf) 102 103#define TRANSFER_COUNT_SET_VCOUNT(x) (((x) & 0xffff) << 16) 104#define TRANSFER_COUNT_GET_VCOUNT(x) (((x) >> 16) & 0xffff) 105#define TRANSFER_COUNT_SET_HCOUNT(x) ((x) & 0xffff) 106#define TRANSFER_COUNT_GET_HCOUNT(x) ((x) & 0xffff) 107 108 109#define VDCTRL0_ENABLE_PRESENT (1 << 28) 110#define VDCTRL0_VSYNC_ACT_HIGH (1 << 27) 111#define VDCTRL0_HSYNC_ACT_HIGH (1 << 26) 112#define VDCTRL0_DOTCLK_ACT_FALLING (1 << 25) 113#define VDCTRL0_ENABLE_ACT_HIGH (1 << 24) 114#define VDCTRL0_VSYNC_PERIOD_UNIT (1 << 21) 115#define VDCTRL0_VSYNC_PULSE_WIDTH_UNIT (1 << 20) 116#define VDCTRL0_HALF_LINE (1 << 19) 117#define VDCTRL0_HALF_LINE_MODE (1 << 18) 118#define VDCTRL0_SET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) 119#define VDCTRL0_GET_VSYNC_PULSE_WIDTH(x) ((x) & 0x3ffff) 120 121#define VDCTRL2_SET_HSYNC_PERIOD(x) ((x) & 0x3ffff) 122#define VDCTRL2_GET_HSYNC_PERIOD(x) ((x) & 0x3ffff) 123 124#define VDCTRL3_MUX_SYNC_SIGNALS (1 << 29) 125#define VDCTRL3_VSYNC_ONLY (1 << 28) 126#define SET_HOR_WAIT_CNT(x) (((x) & 0xfff) << 16) 127#define GET_HOR_WAIT_CNT(x) (((x) >> 16) & 0xfff) 128#define SET_VERT_WAIT_CNT(x) ((x) & 0xffff) 129#define GET_VERT_WAIT_CNT(x) ((x) & 0xffff) 130 131#define VDCTRL4_SET_DOTCLK_DLY(x) (((x) & 0x7) << 29) /* v4 only */ 132#define VDCTRL4_GET_DOTCLK_DLY(x) (((x) >> 29) & 0x7) /* v4 only */ 133#define VDCTRL4_SYNC_SIGNALS_ON (1 << 18) 134#define SET_DOTCLK_H_VALID_DATA_CNT(x) ((x) & 0x3ffff) 135 136#define DEBUG0_HSYNC (1 < 26) 137#define DEBUG0_VSYNC (1 < 25) 138 139#define MIN_XRES 120 140#define MIN_YRES 120 141 142#define RED 0 143#define GREEN 1 144#define BLUE 2 145#define TRANSP 3 146 147#define STMLCDIF_8BIT 1 /** pixel data bus to the display is of 8 bit width */ 148#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */ 149#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */ 150#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */ 151 152#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT (1 << 6) 153#define MXSFB_SYNC_DOTCLK_FALLING_ACT (1 << 7) /* negtive edge sampling */ 154 155enum mxsfb_devtype { 156 MXSFB_V3, 157 MXSFB_V4, 158}; 159 160/* CPU dependent register offsets */ 161struct mxsfb_devdata { 162 unsigned transfer_count; 163 unsigned cur_buf; 164 unsigned next_buf; 165 unsigned debug0; 166 unsigned hs_wdth_mask; 167 unsigned hs_wdth_shift; 168 unsigned ipversion; 169}; 170 171struct mxsfb_info { 172 struct fb_info fb_info; 173 struct platform_device *pdev; 174 struct clk *clk; 175 void __iomem *base; /* registers */ 176 unsigned allocated_size; 177 int enabled; 178 unsigned ld_intf_width; 179 unsigned dotclk_delay; 180 const struct mxsfb_devdata *devdata; 181 u32 sync; 182 struct regulator *reg_lcd; 183}; 184 185#define mxsfb_is_v3(host) (host->devdata->ipversion == 3) 186#define mxsfb_is_v4(host) (host->devdata->ipversion == 4) 187 188static const struct mxsfb_devdata mxsfb_devdata[] = { 189 [MXSFB_V3] = { 190 .transfer_count = LCDC_V3_TRANSFER_COUNT, 191 .cur_buf = LCDC_V3_CUR_BUF, 192 .next_buf = LCDC_V3_NEXT_BUF, 193 .debug0 = LCDC_V3_DEBUG0, 194 .hs_wdth_mask = 0xff, 195 .hs_wdth_shift = 24, 196 .ipversion = 3, 197 }, 198 [MXSFB_V4] = { 199 .transfer_count = LCDC_V4_TRANSFER_COUNT, 200 .cur_buf = LCDC_V4_CUR_BUF, 201 .next_buf = LCDC_V4_NEXT_BUF, 202 .debug0 = LCDC_V4_DEBUG0, 203 .hs_wdth_mask = 0x3fff, 204 .hs_wdth_shift = 18, 205 .ipversion = 4, 206 }, 207}; 208 209#define to_imxfb_host(x) (container_of(x, struct mxsfb_info, fb_info)) 210 211/* mask and shift depends on architecture */ 212static inline u32 set_hsync_pulse_width(struct mxsfb_info *host, unsigned val) 213{ 214 return (val & host->devdata->hs_wdth_mask) << 215 host->devdata->hs_wdth_shift; 216} 217 218static inline u32 get_hsync_pulse_width(struct mxsfb_info *host, unsigned val) 219{ 220 return (val >> host->devdata->hs_wdth_shift) & 221 host->devdata->hs_wdth_mask; 222} 223 224static const struct fb_bitfield def_rgb565[] = { 225 [RED] = { 226 .offset = 11, 227 .length = 5, 228 }, 229 [GREEN] = { 230 .offset = 5, 231 .length = 6, 232 }, 233 [BLUE] = { 234 .offset = 0, 235 .length = 5, 236 }, 237 [TRANSP] = { /* no support for transparency */ 238 .length = 0, 239 } 240}; 241 242static const struct fb_bitfield def_rgb888[] = { 243 [RED] = { 244 .offset = 16, 245 .length = 8, 246 }, 247 [GREEN] = { 248 .offset = 8, 249 .length = 8, 250 }, 251 [BLUE] = { 252 .offset = 0, 253 .length = 8, 254 }, 255 [TRANSP] = { /* no support for transparency */ 256 .length = 0, 257 } 258}; 259 260static inline unsigned chan_to_field(unsigned chan, struct fb_bitfield *bf) 261{ 262 chan &= 0xffff; 263 chan >>= 16 - bf->length; 264 return chan << bf->offset; 265} 266 267static int mxsfb_check_var(struct fb_var_screeninfo *var, 268 struct fb_info *fb_info) 269{ 270 struct mxsfb_info *host = to_imxfb_host(fb_info); 271 const struct fb_bitfield *rgb = NULL; 272 273 if (var->xres < MIN_XRES) 274 var->xres = MIN_XRES; 275 if (var->yres < MIN_YRES) 276 var->yres = MIN_YRES; 277 278 var->xres_virtual = var->xres; 279 280 var->yres_virtual = var->yres; 281 282 switch (var->bits_per_pixel) { 283 case 16: 284 /* always expect RGB 565 */ 285 rgb = def_rgb565; 286 break; 287 case 32: 288 switch (host->ld_intf_width) { 289 case STMLCDIF_8BIT: 290 pr_debug("Unsupported LCD bus width mapping\n"); 291 break; 292 case STMLCDIF_16BIT: 293 case STMLCDIF_18BIT: 294 case STMLCDIF_24BIT: 295 /* real 24 bit */ 296 rgb = def_rgb888; 297 break; 298 } 299 break; 300 default: 301 pr_err("Unsupported colour depth: %u\n", var->bits_per_pixel); 302 return -EINVAL; 303 } 304 305 /* 306 * Copy the RGB parameters for this display 307 * from the machine specific parameters. 308 */ 309 var->red = rgb[RED]; 310 var->green = rgb[GREEN]; 311 var->blue = rgb[BLUE]; 312 var->transp = rgb[TRANSP]; 313 314 return 0; 315} 316 317static void mxsfb_enable_controller(struct fb_info *fb_info) 318{ 319 struct mxsfb_info *host = to_imxfb_host(fb_info); 320 u32 reg; 321 int ret; 322 323 dev_dbg(&host->pdev->dev, "%s\n", __func__); 324 325 if (host->reg_lcd) { 326 ret = regulator_enable(host->reg_lcd); 327 if (ret) { 328 dev_err(&host->pdev->dev, 329 "lcd regulator enable failed: %d\n", ret); 330 return; 331 } 332 } 333 334 clk_prepare_enable(host->clk); 335 clk_set_rate(host->clk, PICOS2KHZ(fb_info->var.pixclock) * 1000U); 336 337 /* if it was disabled, re-enable the mode again */ 338 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_SET); 339 340 /* enable the SYNC signals first, then the DMA engine */ 341 reg = readl(host->base + LCDC_VDCTRL4); 342 reg |= VDCTRL4_SYNC_SIGNALS_ON; 343 writel(reg, host->base + LCDC_VDCTRL4); 344 345 writel(CTRL_RUN, host->base + LCDC_CTRL + REG_SET); 346 347 host->enabled = 1; 348} 349 350static void mxsfb_disable_controller(struct fb_info *fb_info) 351{ 352 struct mxsfb_info *host = to_imxfb_host(fb_info); 353 unsigned loop; 354 u32 reg; 355 int ret; 356 357 dev_dbg(&host->pdev->dev, "%s\n", __func__); 358 359 /* 360 * Even if we disable the controller here, it will still continue 361 * until its FIFOs are running out of data 362 */ 363 writel(CTRL_DOTCLK_MODE, host->base + LCDC_CTRL + REG_CLR); 364 365 loop = 1000; 366 while (loop) { 367 reg = readl(host->base + LCDC_CTRL); 368 if (!(reg & CTRL_RUN)) 369 break; 370 loop--; 371 } 372 373 reg = readl(host->base + LCDC_VDCTRL4); 374 writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); 375 376 clk_disable_unprepare(host->clk); 377 378 host->enabled = 0; 379 380 if (host->reg_lcd) { 381 ret = regulator_disable(host->reg_lcd); 382 if (ret) 383 dev_err(&host->pdev->dev, 384 "lcd regulator disable failed: %d\n", ret); 385 } 386} 387 388static int mxsfb_set_par(struct fb_info *fb_info) 389{ 390 struct mxsfb_info *host = to_imxfb_host(fb_info); 391 u32 ctrl, vdctrl0, vdctrl4; 392 int line_size, fb_size; 393 int reenable = 0; 394 395 line_size = fb_info->var.xres * (fb_info->var.bits_per_pixel >> 3); 396 fb_size = fb_info->var.yres_virtual * line_size; 397 398 if (fb_size > fb_info->fix.smem_len) 399 return -ENOMEM; 400 401 fb_info->fix.line_length = line_size; 402 403 /* 404 * It seems, you can't re-program the controller if it is still running. 405 * This may lead into shifted pictures (FIFO issue?). 406 * So, first stop the controller and drain its FIFOs 407 */ 408 if (host->enabled) { 409 reenable = 1; 410 mxsfb_disable_controller(fb_info); 411 } 412 413 /* clear the FIFOs */ 414 writel(CTRL1_FIFO_CLEAR, host->base + LCDC_CTRL1 + REG_SET); 415 416 ctrl = CTRL_BYPASS_COUNT | CTRL_MASTER | 417 CTRL_SET_BUS_WIDTH(host->ld_intf_width); 418 419 switch (fb_info->var.bits_per_pixel) { 420 case 16: 421 dev_dbg(&host->pdev->dev, "Setting up RGB565 mode\n"); 422 ctrl |= CTRL_SET_WORD_LENGTH(0); 423 writel(CTRL1_SET_BYTE_PACKAGING(0xf), host->base + LCDC_CTRL1); 424 break; 425 case 32: 426 dev_dbg(&host->pdev->dev, "Setting up RGB888/666 mode\n"); 427 ctrl |= CTRL_SET_WORD_LENGTH(3); 428 switch (host->ld_intf_width) { 429 case STMLCDIF_8BIT: 430 dev_err(&host->pdev->dev, 431 "Unsupported LCD bus width mapping\n"); 432 return -EINVAL; 433 case STMLCDIF_16BIT: 434 case STMLCDIF_18BIT: 435 case STMLCDIF_24BIT: 436 /* real 24 bit */ 437 break; 438 } 439 /* do not use packed pixels = one pixel per word instead */ 440 writel(CTRL1_SET_BYTE_PACKAGING(0x7), host->base + LCDC_CTRL1); 441 break; 442 default: 443 dev_err(&host->pdev->dev, "Unhandled color depth of %u\n", 444 fb_info->var.bits_per_pixel); 445 return -EINVAL; 446 } 447 448 writel(ctrl, host->base + LCDC_CTRL); 449 450 writel(TRANSFER_COUNT_SET_VCOUNT(fb_info->var.yres) | 451 TRANSFER_COUNT_SET_HCOUNT(fb_info->var.xres), 452 host->base + host->devdata->transfer_count); 453 454 vdctrl0 = VDCTRL0_ENABLE_PRESENT | /* always in DOTCLOCK mode */ 455 VDCTRL0_VSYNC_PERIOD_UNIT | 456 VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | 457 VDCTRL0_SET_VSYNC_PULSE_WIDTH(fb_info->var.vsync_len); 458 if (fb_info->var.sync & FB_SYNC_HOR_HIGH_ACT) 459 vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH; 460 if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT) 461 vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH; 462 if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT) 463 vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH; 464 if (host->sync & MXSFB_SYNC_DOTCLK_FALLING_ACT) 465 vdctrl0 |= VDCTRL0_DOTCLK_ACT_FALLING; 466 467 writel(vdctrl0, host->base + LCDC_VDCTRL0); 468 469 /* frame length in lines */ 470 writel(fb_info->var.upper_margin + fb_info->var.vsync_len + 471 fb_info->var.lower_margin + fb_info->var.yres, 472 host->base + LCDC_VDCTRL1); 473 474 /* line length in units of clocks or pixels */ 475 writel(set_hsync_pulse_width(host, fb_info->var.hsync_len) | 476 VDCTRL2_SET_HSYNC_PERIOD(fb_info->var.left_margin + 477 fb_info->var.hsync_len + fb_info->var.right_margin + 478 fb_info->var.xres), 479 host->base + LCDC_VDCTRL2); 480 481 writel(SET_HOR_WAIT_CNT(fb_info->var.left_margin + 482 fb_info->var.hsync_len) | 483 SET_VERT_WAIT_CNT(fb_info->var.upper_margin + 484 fb_info->var.vsync_len), 485 host->base + LCDC_VDCTRL3); 486 487 vdctrl4 = SET_DOTCLK_H_VALID_DATA_CNT(fb_info->var.xres); 488 if (mxsfb_is_v4(host)) 489 vdctrl4 |= VDCTRL4_SET_DOTCLK_DLY(host->dotclk_delay); 490 writel(vdctrl4, host->base + LCDC_VDCTRL4); 491 492 writel(fb_info->fix.smem_start + 493 fb_info->fix.line_length * fb_info->var.yoffset, 494 host->base + host->devdata->next_buf); 495 496 if (reenable) 497 mxsfb_enable_controller(fb_info); 498 499 return 0; 500} 501 502static int mxsfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 503 u_int transp, struct fb_info *fb_info) 504{ 505 unsigned int val; 506 int ret = -EINVAL; 507 508 /* 509 * If greyscale is true, then we convert the RGB value 510 * to greyscale no matter what visual we are using. 511 */ 512 if (fb_info->var.grayscale) 513 red = green = blue = (19595 * red + 38470 * green + 514 7471 * blue) >> 16; 515 516 switch (fb_info->fix.visual) { 517 case FB_VISUAL_TRUECOLOR: 518 /* 519 * 12 or 16-bit True Colour. We encode the RGB value 520 * according to the RGB bitfield information. 521 */ 522 if (regno < 16) { 523 u32 *pal = fb_info->pseudo_palette; 524 525 val = chan_to_field(red, &fb_info->var.red); 526 val |= chan_to_field(green, &fb_info->var.green); 527 val |= chan_to_field(blue, &fb_info->var.blue); 528 529 pal[regno] = val; 530 ret = 0; 531 } 532 break; 533 534 case FB_VISUAL_STATIC_PSEUDOCOLOR: 535 case FB_VISUAL_PSEUDOCOLOR: 536 break; 537 } 538 539 return ret; 540} 541 542static int mxsfb_blank(int blank, struct fb_info *fb_info) 543{ 544 struct mxsfb_info *host = to_imxfb_host(fb_info); 545 546 switch (blank) { 547 case FB_BLANK_POWERDOWN: 548 case FB_BLANK_VSYNC_SUSPEND: 549 case FB_BLANK_HSYNC_SUSPEND: 550 case FB_BLANK_NORMAL: 551 if (host->enabled) 552 mxsfb_disable_controller(fb_info); 553 break; 554 555 case FB_BLANK_UNBLANK: 556 if (!host->enabled) 557 mxsfb_enable_controller(fb_info); 558 break; 559 } 560 return 0; 561} 562 563static int mxsfb_pan_display(struct fb_var_screeninfo *var, 564 struct fb_info *fb_info) 565{ 566 struct mxsfb_info *host = to_imxfb_host(fb_info); 567 unsigned offset; 568 569 if (var->xoffset != 0) 570 return -EINVAL; 571 572 offset = fb_info->fix.line_length * var->yoffset; 573 574 /* update on next VSYNC */ 575 writel(fb_info->fix.smem_start + offset, 576 host->base + host->devdata->next_buf); 577 578 return 0; 579} 580 581static struct fb_ops mxsfb_ops = { 582 .owner = THIS_MODULE, 583 .fb_check_var = mxsfb_check_var, 584 .fb_set_par = mxsfb_set_par, 585 .fb_setcolreg = mxsfb_setcolreg, 586 .fb_blank = mxsfb_blank, 587 .fb_pan_display = mxsfb_pan_display, 588 .fb_fillrect = cfb_fillrect, 589 .fb_copyarea = cfb_copyarea, 590 .fb_imageblit = cfb_imageblit, 591}; 592 593static int mxsfb_restore_mode(struct mxsfb_info *host, 594 struct fb_videomode *vmode) 595{ 596 struct fb_info *fb_info = &host->fb_info; 597 unsigned line_count; 598 unsigned period; 599 unsigned long pa, fbsize; 600 int bits_per_pixel, ofs; 601 u32 transfer_count, vdctrl0, vdctrl2, vdctrl3, vdctrl4, ctrl; 602 603 /* Only restore the mode when the controller is running */ 604 ctrl = readl(host->base + LCDC_CTRL); 605 if (!(ctrl & CTRL_RUN)) 606 return -EINVAL; 607 608 vdctrl0 = readl(host->base + LCDC_VDCTRL0); 609 vdctrl2 = readl(host->base + LCDC_VDCTRL2); 610 vdctrl3 = readl(host->base + LCDC_VDCTRL3); 611 vdctrl4 = readl(host->base + LCDC_VDCTRL4); 612 613 transfer_count = readl(host->base + host->devdata->transfer_count); 614 615 vmode->xres = TRANSFER_COUNT_GET_HCOUNT(transfer_count); 616 vmode->yres = TRANSFER_COUNT_GET_VCOUNT(transfer_count); 617 618 switch (CTRL_GET_WORD_LENGTH(ctrl)) { 619 case 0: 620 bits_per_pixel = 16; 621 break; 622 case 3: 623 bits_per_pixel = 32; 624 break; 625 case 1: 626 default: 627 return -EINVAL; 628 } 629 630 fb_info->var.bits_per_pixel = bits_per_pixel; 631 632 vmode->pixclock = KHZ2PICOS(clk_get_rate(host->clk) / 1000U); 633 vmode->hsync_len = get_hsync_pulse_width(host, vdctrl2); 634 vmode->left_margin = GET_HOR_WAIT_CNT(vdctrl3) - vmode->hsync_len; 635 vmode->right_margin = VDCTRL2_GET_HSYNC_PERIOD(vdctrl2) - 636 vmode->hsync_len - vmode->left_margin - vmode->xres; 637 vmode->vsync_len = VDCTRL0_GET_VSYNC_PULSE_WIDTH(vdctrl0); 638 period = readl(host->base + LCDC_VDCTRL1); 639 vmode->upper_margin = GET_VERT_WAIT_CNT(vdctrl3) - vmode->vsync_len; 640 vmode->lower_margin = period - vmode->vsync_len - 641 vmode->upper_margin - vmode->yres; 642 643 vmode->vmode = FB_VMODE_NONINTERLACED; 644 645 vmode->sync = 0; 646 if (vdctrl0 & VDCTRL0_HSYNC_ACT_HIGH) 647 vmode->sync |= FB_SYNC_HOR_HIGH_ACT; 648 if (vdctrl0 & VDCTRL0_VSYNC_ACT_HIGH) 649 vmode->sync |= FB_SYNC_VERT_HIGH_ACT; 650 651 pr_debug("Reconstructed video mode:\n"); 652 pr_debug("%dx%d, hsync: %u left: %u, right: %u, vsync: %u, upper: %u, lower: %u\n", 653 vmode->xres, vmode->yres, vmode->hsync_len, vmode->left_margin, 654 vmode->right_margin, vmode->vsync_len, vmode->upper_margin, 655 vmode->lower_margin); 656 pr_debug("pixclk: %ldkHz\n", PICOS2KHZ(vmode->pixclock)); 657 658 host->ld_intf_width = CTRL_GET_BUS_WIDTH(ctrl); 659 host->dotclk_delay = VDCTRL4_GET_DOTCLK_DLY(vdctrl4); 660 661 fb_info->fix.line_length = vmode->xres * (bits_per_pixel >> 3); 662 663 pa = readl(host->base + host->devdata->cur_buf); 664 fbsize = fb_info->fix.line_length * vmode->yres; 665 if (pa < fb_info->fix.smem_start) 666 return -EINVAL; 667 if (pa + fbsize > fb_info->fix.smem_start + fb_info->fix.smem_len) 668 return -EINVAL; 669 ofs = pa - fb_info->fix.smem_start; 670 if (ofs) { 671 memmove(fb_info->screen_base, fb_info->screen_base + ofs, fbsize); 672 writel(fb_info->fix.smem_start, host->base + host->devdata->next_buf); 673 } 674 675 line_count = fb_info->fix.smem_len / fb_info->fix.line_length; 676 fb_info->fix.ypanstep = 1; 677 678 clk_prepare_enable(host->clk); 679 host->enabled = 1; 680 681 return 0; 682} 683 684static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host, 685 struct fb_videomode *vmode) 686{ 687 struct fb_info *fb_info = &host->fb_info; 688 struct fb_var_screeninfo *var = &fb_info->var; 689 struct device *dev = &host->pdev->dev; 690 struct device_node *np = host->pdev->dev.of_node; 691 struct device_node *display_np; 692 struct videomode vm; 693 u32 width; 694 int ret; 695 696 display_np = of_parse_phandle(np, "display", 0); 697 if (!display_np) { 698 dev_err(dev, "failed to find display phandle\n"); 699 return -ENOENT; 700 } 701 702 ret = of_property_read_u32(display_np, "bus-width", &width); 703 if (ret < 0) { 704 dev_err(dev, "failed to get property bus-width\n"); 705 goto put_display_node; 706 } 707 708 switch (width) { 709 case 8: 710 host->ld_intf_width = STMLCDIF_8BIT; 711 break; 712 case 16: 713 host->ld_intf_width = STMLCDIF_16BIT; 714 break; 715 case 18: 716 host->ld_intf_width = STMLCDIF_18BIT; 717 break; 718 case 24: 719 host->ld_intf_width = STMLCDIF_24BIT; 720 break; 721 default: 722 dev_err(dev, "invalid bus-width value\n"); 723 ret = -EINVAL; 724 goto put_display_node; 725 } 726 727 ret = of_property_read_u32(display_np, "bits-per-pixel", 728 &var->bits_per_pixel); 729 if (ret < 0) { 730 dev_err(dev, "failed to get property bits-per-pixel\n"); 731 goto put_display_node; 732 } 733 734 ret = of_get_videomode(display_np, &vm, OF_USE_NATIVE_MODE); 735 if (ret) { 736 dev_err(dev, "failed to get videomode from DT\n"); 737 goto put_display_node; 738 } 739 740 ret = fb_videomode_from_videomode(&vm, vmode); 741 if (ret < 0) 742 goto put_display_node; 743 744 if (vm.flags & DISPLAY_FLAGS_DE_HIGH) 745 host->sync |= MXSFB_SYNC_DATA_ENABLE_HIGH_ACT; 746 if (vm.flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) 747 host->sync |= MXSFB_SYNC_DOTCLK_FALLING_ACT; 748 749put_display_node: 750 of_node_put(display_np); 751 return ret; 752} 753 754static int mxsfb_init_fbinfo(struct mxsfb_info *host, 755 struct fb_videomode *vmode) 756{ 757 int ret; 758 struct fb_info *fb_info = &host->fb_info; 759 struct fb_var_screeninfo *var = &fb_info->var; 760 dma_addr_t fb_phys; 761 void *fb_virt; 762 unsigned fb_size; 763 764 fb_info->fbops = &mxsfb_ops; 765 fb_info->flags = FBINFO_FLAG_DEFAULT | FBINFO_READS_FAST; 766 strlcpy(fb_info->fix.id, "mxs", sizeof(fb_info->fix.id)); 767 fb_info->fix.type = FB_TYPE_PACKED_PIXELS; 768 fb_info->fix.ypanstep = 1; 769 fb_info->fix.visual = FB_VISUAL_TRUECOLOR, 770 fb_info->fix.accel = FB_ACCEL_NONE; 771 772 ret = mxsfb_init_fbinfo_dt(host, vmode); 773 if (ret) 774 return ret; 775 776 var->nonstd = 0; 777 var->activate = FB_ACTIVATE_NOW; 778 var->accel_flags = 0; 779 var->vmode = FB_VMODE_NONINTERLACED; 780 781 /* Memory allocation for framebuffer */ 782 fb_size = SZ_2M; 783 fb_virt = alloc_pages_exact(fb_size, GFP_DMA); 784 if (!fb_virt) 785 return -ENOMEM; 786 787 fb_phys = virt_to_phys(fb_virt); 788 789 fb_info->fix.smem_start = fb_phys; 790 fb_info->screen_base = fb_virt; 791 fb_info->screen_size = fb_info->fix.smem_len = fb_size; 792 793 if (mxsfb_restore_mode(host, vmode)) 794 memset(fb_virt, 0, fb_size); 795 796 return 0; 797} 798 799static void mxsfb_free_videomem(struct mxsfb_info *host) 800{ 801 struct fb_info *fb_info = &host->fb_info; 802 803 free_pages_exact(fb_info->screen_base, fb_info->fix.smem_len); 804} 805 806static struct platform_device_id mxsfb_devtype[] = { 807 { 808 .name = "imx23-fb", 809 .driver_data = MXSFB_V3, 810 }, { 811 .name = "imx28-fb", 812 .driver_data = MXSFB_V4, 813 }, { 814 /* sentinel */ 815 } 816}; 817MODULE_DEVICE_TABLE(platform, mxsfb_devtype); 818 819static const struct of_device_id mxsfb_dt_ids[] = { 820 { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], }, 821 { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], }, 822 { /* sentinel */ } 823}; 824MODULE_DEVICE_TABLE(of, mxsfb_dt_ids); 825 826static int mxsfb_probe(struct platform_device *pdev) 827{ 828 const struct of_device_id *of_id = 829 of_match_device(mxsfb_dt_ids, &pdev->dev); 830 struct resource *res; 831 struct mxsfb_info *host; 832 struct fb_info *fb_info; 833 struct fb_videomode *mode; 834 int ret; 835 836 if (of_id) 837 pdev->id_entry = of_id->data; 838 839 fb_info = framebuffer_alloc(sizeof(struct mxsfb_info), &pdev->dev); 840 if (!fb_info) { 841 dev_err(&pdev->dev, "Failed to allocate fbdev\n"); 842 return -ENOMEM; 843 } 844 845 mode = devm_kzalloc(&pdev->dev, sizeof(struct fb_videomode), 846 GFP_KERNEL); 847 if (mode == NULL) 848 return -ENOMEM; 849 850 host = to_imxfb_host(fb_info); 851 852 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 853 host->base = devm_ioremap_resource(&pdev->dev, res); 854 if (IS_ERR(host->base)) { 855 ret = PTR_ERR(host->base); 856 goto fb_release; 857 } 858 859 host->pdev = pdev; 860 platform_set_drvdata(pdev, host); 861 862 host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; 863 864 host->clk = devm_clk_get(&host->pdev->dev, NULL); 865 if (IS_ERR(host->clk)) { 866 ret = PTR_ERR(host->clk); 867 goto fb_release; 868 } 869 870 host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd"); 871 if (IS_ERR(host->reg_lcd)) 872 host->reg_lcd = NULL; 873 874 fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16, 875 GFP_KERNEL); 876 if (!fb_info->pseudo_palette) { 877 ret = -ENOMEM; 878 goto fb_release; 879 } 880 881 ret = mxsfb_init_fbinfo(host, mode); 882 if (ret != 0) 883 goto fb_release; 884 885 fb_videomode_to_var(&fb_info->var, mode); 886 887 /* init the color fields */ 888 mxsfb_check_var(&fb_info->var, fb_info); 889 890 platform_set_drvdata(pdev, fb_info); 891 892 ret = register_framebuffer(fb_info); 893 if (ret != 0) { 894 dev_err(&pdev->dev,"Failed to register framebuffer\n"); 895 goto fb_destroy; 896 } 897 898 if (!host->enabled) { 899 writel(0, host->base + LCDC_CTRL); 900 mxsfb_set_par(fb_info); 901 mxsfb_enable_controller(fb_info); 902 } 903 904 dev_info(&pdev->dev, "initialized\n"); 905 906 return 0; 907 908fb_destroy: 909 if (host->enabled) 910 clk_disable_unprepare(host->clk); 911fb_release: 912 framebuffer_release(fb_info); 913 914 return ret; 915} 916 917static int mxsfb_remove(struct platform_device *pdev) 918{ 919 struct fb_info *fb_info = platform_get_drvdata(pdev); 920 struct mxsfb_info *host = to_imxfb_host(fb_info); 921 922 if (host->enabled) 923 mxsfb_disable_controller(fb_info); 924 925 unregister_framebuffer(fb_info); 926 mxsfb_free_videomem(host); 927 928 framebuffer_release(fb_info); 929 930 return 0; 931} 932 933static void mxsfb_shutdown(struct platform_device *pdev) 934{ 935 struct fb_info *fb_info = platform_get_drvdata(pdev); 936 struct mxsfb_info *host = to_imxfb_host(fb_info); 937 938 /* 939 * Force stop the LCD controller as keeping it running during reboot 940 * might interfere with the BootROM's boot mode pads sampling. 941 */ 942 writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR); 943} 944 945static struct platform_driver mxsfb_driver = { 946 .probe = mxsfb_probe, 947 .remove = mxsfb_remove, 948 .shutdown = mxsfb_shutdown, 949 .id_table = mxsfb_devtype, 950 .driver = { 951 .name = DRIVER_NAME, 952 .of_match_table = mxsfb_dt_ids, 953 }, 954}; 955 956module_platform_driver(mxsfb_driver); 957 958MODULE_DESCRIPTION("Freescale mxs framebuffer driver"); 959MODULE_AUTHOR("Sascha Hauer, Pengutronix"); 960MODULE_LICENSE("GPL"); 961