1/* 2 * linux/drivers/video/omap2/dss/dss.c 3 * 4 * Copyright (C) 2009 Nokia Corporation 5 * Author: Tomi Valkeinen <tomi.valkeinen@nokia.com> 6 * 7 * Some code and ideas taken from drivers/video/omap/ driver 8 * by Imre Deak. 9 * 10 * This program is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License version 2 as published by 12 * the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but WITHOUT 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 17 * more details. 18 * 19 * You should have received a copy of the GNU General Public License along with 20 * this program. If not, see <http://www.gnu.org/licenses/>. 21 */ 22 23#define DSS_SUBSYS_NAME "DSS" 24 25#include <linux/kernel.h> 26#include <linux/module.h> 27#include <linux/io.h> 28#include <linux/export.h> 29#include <linux/err.h> 30#include <linux/delay.h> 31#include <linux/seq_file.h> 32#include <linux/clk.h> 33#include <linux/platform_device.h> 34#include <linux/pm_runtime.h> 35#include <linux/gfp.h> 36#include <linux/sizes.h> 37#include <linux/of.h> 38 39#include <video/omapdss.h> 40 41#include "dss.h" 42#include "dss_features.h" 43 44#define DSS_SZ_REGS SZ_512 45 46struct dss_reg { 47 u16 idx; 48}; 49 50#define DSS_REG(idx) ((const struct dss_reg) { idx }) 51 52#define DSS_REVISION DSS_REG(0x0000) 53#define DSS_SYSCONFIG DSS_REG(0x0010) 54#define DSS_SYSSTATUS DSS_REG(0x0014) 55#define DSS_CONTROL DSS_REG(0x0040) 56#define DSS_SDI_CONTROL DSS_REG(0x0044) 57#define DSS_PLL_CONTROL DSS_REG(0x0048) 58#define DSS_SDI_STATUS DSS_REG(0x005C) 59 60#define REG_GET(idx, start, end) \ 61 FLD_GET(dss_read_reg(idx), start, end) 62 63#define REG_FLD_MOD(idx, val, start, end) \ 64 dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end)) 65 66static int dss_runtime_get(void); 67static void dss_runtime_put(void); 68 69struct dss_features { 70 u8 fck_div_max; 71 u8 dss_fck_multiplier; 72 const char *parent_clk_name; 73 int (*dpi_select_source)(enum omap_channel channel); 74}; 75 76static struct { 77 struct platform_device *pdev; 78 void __iomem *base; 79 80 struct clk *parent_clk; 81 struct clk *dss_clk; 82 unsigned long dss_clk_rate; 83 84 unsigned long cache_req_pck; 85 unsigned long cache_prate; 86 struct dispc_clock_info cache_dispc_cinfo; 87 88 enum omap_dss_clk_source dsi_clk_source[MAX_NUM_DSI]; 89 enum omap_dss_clk_source dispc_clk_source; 90 enum omap_dss_clk_source lcd_clk_source[MAX_DSS_LCD_MANAGERS]; 91 92 bool ctx_valid; 93 u32 ctx[DSS_SZ_REGS / sizeof(u32)]; 94 95 const struct dss_features *feat; 96} dss; 97 98static const char * const dss_generic_clk_source_names[] = { 99 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC] = "DSI_PLL_HSDIV_DISPC", 100 [OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI] = "DSI_PLL_HSDIV_DSI", 101 [OMAP_DSS_CLK_SRC_FCK] = "DSS_FCK", 102 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC] = "DSI_PLL2_HSDIV_DISPC", 103 [OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI] = "DSI_PLL2_HSDIV_DSI", 104}; 105 106static inline void dss_write_reg(const struct dss_reg idx, u32 val) 107{ 108 __raw_writel(val, dss.base + idx.idx); 109} 110 111static inline u32 dss_read_reg(const struct dss_reg idx) 112{ 113 return __raw_readl(dss.base + idx.idx); 114} 115 116#define SR(reg) \ 117 dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg) 118#define RR(reg) \ 119 dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)]) 120 121static void dss_save_context(void) 122{ 123 DSSDBG("dss_save_context\n"); 124 125 SR(CONTROL); 126 127 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & 128 OMAP_DISPLAY_TYPE_SDI) { 129 SR(SDI_CONTROL); 130 SR(PLL_CONTROL); 131 } 132 133 dss.ctx_valid = true; 134 135 DSSDBG("context saved\n"); 136} 137 138static void dss_restore_context(void) 139{ 140 DSSDBG("dss_restore_context\n"); 141 142 if (!dss.ctx_valid) 143 return; 144 145 RR(CONTROL); 146 147 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & 148 OMAP_DISPLAY_TYPE_SDI) { 149 RR(SDI_CONTROL); 150 RR(PLL_CONTROL); 151 } 152 153 DSSDBG("context restored\n"); 154} 155 156#undef SR 157#undef RR 158 159void dss_sdi_init(int datapairs) 160{ 161 u32 l; 162 163 BUG_ON(datapairs > 3 || datapairs < 1); 164 165 l = dss_read_reg(DSS_SDI_CONTROL); 166 l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */ 167 l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */ 168 l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */ 169 dss_write_reg(DSS_SDI_CONTROL, l); 170 171 l = dss_read_reg(DSS_PLL_CONTROL); 172 l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */ 173 l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */ 174 l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */ 175 dss_write_reg(DSS_PLL_CONTROL, l); 176} 177 178int dss_sdi_enable(void) 179{ 180 unsigned long timeout; 181 182 dispc_pck_free_enable(1); 183 184 /* Reset SDI PLL */ 185 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */ 186 udelay(1); /* wait 2x PCLK */ 187 188 /* Lock SDI PLL */ 189 REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */ 190 191 /* Waiting for PLL lock request to complete */ 192 timeout = jiffies + msecs_to_jiffies(500); 193 while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) { 194 if (time_after_eq(jiffies, timeout)) { 195 DSSERR("PLL lock request timed out\n"); 196 goto err1; 197 } 198 } 199 200 /* Clearing PLL_GO bit */ 201 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28); 202 203 /* Waiting for PLL to lock */ 204 timeout = jiffies + msecs_to_jiffies(500); 205 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) { 206 if (time_after_eq(jiffies, timeout)) { 207 DSSERR("PLL lock timed out\n"); 208 goto err1; 209 } 210 } 211 212 dispc_lcd_enable_signal(1); 213 214 /* Waiting for SDI reset to complete */ 215 timeout = jiffies + msecs_to_jiffies(500); 216 while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) { 217 if (time_after_eq(jiffies, timeout)) { 218 DSSERR("SDI reset timed out\n"); 219 goto err2; 220 } 221 } 222 223 return 0; 224 225 err2: 226 dispc_lcd_enable_signal(0); 227 err1: 228 /* Reset SDI PLL */ 229 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ 230 231 dispc_pck_free_enable(0); 232 233 return -ETIMEDOUT; 234} 235 236void dss_sdi_disable(void) 237{ 238 dispc_lcd_enable_signal(0); 239 240 dispc_pck_free_enable(0); 241 242 /* Reset SDI PLL */ 243 REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */ 244} 245 246const char *dss_get_generic_clk_source_name(enum omap_dss_clk_source clk_src) 247{ 248 return dss_generic_clk_source_names[clk_src]; 249} 250 251void dss_dump_clocks(struct seq_file *s) 252{ 253 const char *fclk_name, *fclk_real_name; 254 unsigned long fclk_rate; 255 256 if (dss_runtime_get()) 257 return; 258 259 seq_printf(s, "- DSS -\n"); 260 261 fclk_name = dss_get_generic_clk_source_name(OMAP_DSS_CLK_SRC_FCK); 262 fclk_real_name = dss_feat_get_clk_source_name(OMAP_DSS_CLK_SRC_FCK); 263 fclk_rate = clk_get_rate(dss.dss_clk); 264 265 seq_printf(s, "%s (%s) = %lu\n", 266 fclk_name, fclk_real_name, 267 fclk_rate); 268 269 dss_runtime_put(); 270} 271 272static void dss_dump_regs(struct seq_file *s) 273{ 274#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r)) 275 276 if (dss_runtime_get()) 277 return; 278 279 DUMPREG(DSS_REVISION); 280 DUMPREG(DSS_SYSCONFIG); 281 DUMPREG(DSS_SYSSTATUS); 282 DUMPREG(DSS_CONTROL); 283 284 if (dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_LCD) & 285 OMAP_DISPLAY_TYPE_SDI) { 286 DUMPREG(DSS_SDI_CONTROL); 287 DUMPREG(DSS_PLL_CONTROL); 288 DUMPREG(DSS_SDI_STATUS); 289 } 290 291 dss_runtime_put(); 292#undef DUMPREG 293} 294 295static void dss_select_dispc_clk_source(enum omap_dss_clk_source clk_src) 296{ 297 struct platform_device *dsidev; 298 int b; 299 u8 start, end; 300 301 switch (clk_src) { 302 case OMAP_DSS_CLK_SRC_FCK: 303 b = 0; 304 break; 305 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 306 b = 1; 307 dsidev = dsi_get_dsidev_from_id(0); 308 dsi_wait_pll_hsdiv_dispc_active(dsidev); 309 break; 310 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 311 b = 2; 312 dsidev = dsi_get_dsidev_from_id(1); 313 dsi_wait_pll_hsdiv_dispc_active(dsidev); 314 break; 315 default: 316 BUG(); 317 return; 318 } 319 320 dss_feat_get_reg_field(FEAT_REG_DISPC_CLK_SWITCH, &start, &end); 321 322 REG_FLD_MOD(DSS_CONTROL, b, start, end); /* DISPC_CLK_SWITCH */ 323 324 dss.dispc_clk_source = clk_src; 325} 326 327void dss_select_dsi_clk_source(int dsi_module, 328 enum omap_dss_clk_source clk_src) 329{ 330 struct platform_device *dsidev; 331 int b, pos; 332 333 switch (clk_src) { 334 case OMAP_DSS_CLK_SRC_FCK: 335 b = 0; 336 break; 337 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI: 338 BUG_ON(dsi_module != 0); 339 b = 1; 340 dsidev = dsi_get_dsidev_from_id(0); 341 dsi_wait_pll_hsdiv_dsi_active(dsidev); 342 break; 343 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI: 344 BUG_ON(dsi_module != 1); 345 b = 1; 346 dsidev = dsi_get_dsidev_from_id(1); 347 dsi_wait_pll_hsdiv_dsi_active(dsidev); 348 break; 349 default: 350 BUG(); 351 return; 352 } 353 354 pos = dsi_module == 0 ? 1 : 10; 355 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* DSIx_CLK_SWITCH */ 356 357 dss.dsi_clk_source[dsi_module] = clk_src; 358} 359 360void dss_select_lcd_clk_source(enum omap_channel channel, 361 enum omap_dss_clk_source clk_src) 362{ 363 struct platform_device *dsidev; 364 int b, ix, pos; 365 366 if (!dss_has_feature(FEAT_LCD_CLK_SRC)) { 367 dss_select_dispc_clk_source(clk_src); 368 return; 369 } 370 371 switch (clk_src) { 372 case OMAP_DSS_CLK_SRC_FCK: 373 b = 0; 374 break; 375 case OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC: 376 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD); 377 b = 1; 378 dsidev = dsi_get_dsidev_from_id(0); 379 dsi_wait_pll_hsdiv_dispc_active(dsidev); 380 break; 381 case OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC: 382 BUG_ON(channel != OMAP_DSS_CHANNEL_LCD2 && 383 channel != OMAP_DSS_CHANNEL_LCD3); 384 b = 1; 385 dsidev = dsi_get_dsidev_from_id(1); 386 dsi_wait_pll_hsdiv_dispc_active(dsidev); 387 break; 388 default: 389 BUG(); 390 return; 391 } 392 393 pos = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 394 (channel == OMAP_DSS_CHANNEL_LCD2 ? 12 : 19); 395 REG_FLD_MOD(DSS_CONTROL, b, pos, pos); /* LCDx_CLK_SWITCH */ 396 397 ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 398 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2); 399 dss.lcd_clk_source[ix] = clk_src; 400} 401 402enum omap_dss_clk_source dss_get_dispc_clk_source(void) 403{ 404 return dss.dispc_clk_source; 405} 406 407enum omap_dss_clk_source dss_get_dsi_clk_source(int dsi_module) 408{ 409 return dss.dsi_clk_source[dsi_module]; 410} 411 412enum omap_dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel) 413{ 414 if (dss_has_feature(FEAT_LCD_CLK_SRC)) { 415 int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 416 (channel == OMAP_DSS_CHANNEL_LCD2 ? 1 : 2); 417 return dss.lcd_clk_source[ix]; 418 } else { 419 /* LCD_CLK source is the same as DISPC_FCLK source for 420 * OMAP2 and OMAP3 */ 421 return dss.dispc_clk_source; 422 } 423} 424 425bool dss_div_calc(unsigned long pck, unsigned long fck_min, 426 dss_div_calc_func func, void *data) 427{ 428 int fckd, fckd_start, fckd_stop; 429 unsigned long fck; 430 unsigned long fck_hw_max; 431 unsigned long fckd_hw_max; 432 unsigned long prate; 433 unsigned m; 434 435 fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 436 437 if (dss.parent_clk == NULL) { 438 unsigned pckd; 439 440 pckd = fck_hw_max / pck; 441 442 fck = pck * pckd; 443 444 fck = clk_round_rate(dss.dss_clk, fck); 445 446 return func(fck, data); 447 } 448 449 fckd_hw_max = dss.feat->fck_div_max; 450 451 m = dss.feat->dss_fck_multiplier; 452 prate = clk_get_rate(dss.parent_clk); 453 454 fck_min = fck_min ? fck_min : 1; 455 456 fckd_start = min(prate * m / fck_min, fckd_hw_max); 457 fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul); 458 459 for (fckd = fckd_start; fckd >= fckd_stop; --fckd) { 460 fck = DIV_ROUND_UP(prate, fckd) * m; 461 462 if (func(fck, data)) 463 return true; 464 } 465 466 return false; 467} 468 469int dss_set_fck_rate(unsigned long rate) 470{ 471 int r; 472 473 DSSDBG("set fck to %lu\n", rate); 474 475 r = clk_set_rate(dss.dss_clk, rate); 476 if (r) 477 return r; 478 479 dss.dss_clk_rate = clk_get_rate(dss.dss_clk); 480 481 WARN_ONCE(dss.dss_clk_rate != rate, 482 "clk rate mismatch: %lu != %lu", dss.dss_clk_rate, 483 rate); 484 485 return 0; 486} 487 488unsigned long dss_get_dispc_clk_rate(void) 489{ 490 return dss.dss_clk_rate; 491} 492 493static int dss_setup_default_clock(void) 494{ 495 unsigned long max_dss_fck, prate; 496 unsigned long fck; 497 unsigned fck_div; 498 int r; 499 500 max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); 501 502 if (dss.parent_clk == NULL) { 503 fck = clk_round_rate(dss.dss_clk, max_dss_fck); 504 } else { 505 prate = clk_get_rate(dss.parent_clk); 506 507 fck_div = DIV_ROUND_UP(prate * dss.feat->dss_fck_multiplier, 508 max_dss_fck); 509 fck = DIV_ROUND_UP(prate, fck_div) * dss.feat->dss_fck_multiplier; 510 } 511 512 r = dss_set_fck_rate(fck); 513 if (r) 514 return r; 515 516 return 0; 517} 518 519void dss_set_venc_output(enum omap_dss_venc_type type) 520{ 521 int l = 0; 522 523 if (type == OMAP_DSS_VENC_TYPE_COMPOSITE) 524 l = 0; 525 else if (type == OMAP_DSS_VENC_TYPE_SVIDEO) 526 l = 1; 527 else 528 BUG(); 529 530 /* venc out selection. 0 = comp, 1 = svideo */ 531 REG_FLD_MOD(DSS_CONTROL, l, 6, 6); 532} 533 534void dss_set_dac_pwrdn_bgz(bool enable) 535{ 536 REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */ 537} 538 539void dss_select_hdmi_venc_clk_source(enum dss_hdmi_venc_clk_source_select src) 540{ 541 enum omap_display_type dp; 542 dp = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT); 543 544 /* Complain about invalid selections */ 545 WARN_ON((src == DSS_VENC_TV_CLK) && !(dp & OMAP_DISPLAY_TYPE_VENC)); 546 WARN_ON((src == DSS_HDMI_M_PCLK) && !(dp & OMAP_DISPLAY_TYPE_HDMI)); 547 548 /* Select only if we have options */ 549 if ((dp & OMAP_DISPLAY_TYPE_VENC) && (dp & OMAP_DISPLAY_TYPE_HDMI)) 550 REG_FLD_MOD(DSS_CONTROL, src, 15, 15); /* VENC_HDMI_SWITCH */ 551} 552 553enum dss_hdmi_venc_clk_source_select dss_get_hdmi_venc_clk_source(void) 554{ 555 enum omap_display_type displays; 556 557 displays = dss_feat_get_supported_displays(OMAP_DSS_CHANNEL_DIGIT); 558 if ((displays & OMAP_DISPLAY_TYPE_HDMI) == 0) 559 return DSS_VENC_TV_CLK; 560 561 if ((displays & OMAP_DISPLAY_TYPE_VENC) == 0) 562 return DSS_HDMI_M_PCLK; 563 564 return REG_GET(DSS_CONTROL, 15, 15); 565} 566 567static int dss_dpi_select_source_omap2_omap3(enum omap_channel channel) 568{ 569 if (channel != OMAP_DSS_CHANNEL_LCD) 570 return -EINVAL; 571 572 return 0; 573} 574 575static int dss_dpi_select_source_omap4(enum omap_channel channel) 576{ 577 int val; 578 579 switch (channel) { 580 case OMAP_DSS_CHANNEL_LCD2: 581 val = 0; 582 break; 583 case OMAP_DSS_CHANNEL_DIGIT: 584 val = 1; 585 break; 586 default: 587 return -EINVAL; 588 } 589 590 REG_FLD_MOD(DSS_CONTROL, val, 17, 17); 591 592 return 0; 593} 594 595static int dss_dpi_select_source_omap5(enum omap_channel channel) 596{ 597 int val; 598 599 switch (channel) { 600 case OMAP_DSS_CHANNEL_LCD: 601 val = 1; 602 break; 603 case OMAP_DSS_CHANNEL_LCD2: 604 val = 2; 605 break; 606 case OMAP_DSS_CHANNEL_LCD3: 607 val = 3; 608 break; 609 case OMAP_DSS_CHANNEL_DIGIT: 610 val = 0; 611 break; 612 default: 613 return -EINVAL; 614 } 615 616 REG_FLD_MOD(DSS_CONTROL, val, 17, 16); 617 618 return 0; 619} 620 621int dss_dpi_select_source(enum omap_channel channel) 622{ 623 return dss.feat->dpi_select_source(channel); 624} 625 626static int dss_get_clocks(void) 627{ 628 struct clk *clk; 629 630 clk = devm_clk_get(&dss.pdev->dev, "fck"); 631 if (IS_ERR(clk)) { 632 DSSERR("can't get clock fck\n"); 633 return PTR_ERR(clk); 634 } 635 636 dss.dss_clk = clk; 637 638 if (dss.feat->parent_clk_name) { 639 clk = clk_get(NULL, dss.feat->parent_clk_name); 640 if (IS_ERR(clk)) { 641 DSSERR("Failed to get %s\n", dss.feat->parent_clk_name); 642 return PTR_ERR(clk); 643 } 644 } else { 645 clk = NULL; 646 } 647 648 dss.parent_clk = clk; 649 650 return 0; 651} 652 653static void dss_put_clocks(void) 654{ 655 if (dss.parent_clk) 656 clk_put(dss.parent_clk); 657} 658 659static int dss_runtime_get(void) 660{ 661 int r; 662 663 DSSDBG("dss_runtime_get\n"); 664 665 r = pm_runtime_get_sync(&dss.pdev->dev); 666 WARN_ON(r < 0); 667 return r < 0 ? r : 0; 668} 669 670static void dss_runtime_put(void) 671{ 672 int r; 673 674 DSSDBG("dss_runtime_put\n"); 675 676 r = pm_runtime_put_sync(&dss.pdev->dev); 677 WARN_ON(r < 0 && r != -ENOSYS && r != -EBUSY); 678} 679 680/* DEBUGFS */ 681#if defined(CONFIG_OMAP2_DSS_DEBUGFS) 682void dss_debug_dump_clocks(struct seq_file *s) 683{ 684 dss_dump_clocks(s); 685 dispc_dump_clocks(s); 686#ifdef CONFIG_OMAP2_DSS_DSI 687 dsi_dump_clocks(s); 688#endif 689} 690#endif 691 692static const struct dss_features omap24xx_dss_feats __initconst = { 693 /* 694 * fck div max is really 16, but the divider range has gaps. The range 695 * from 1 to 6 has no gaps, so let's use that as a max. 696 */ 697 .fck_div_max = 6, 698 .dss_fck_multiplier = 2, 699 .parent_clk_name = "core_ck", 700 .dpi_select_source = &dss_dpi_select_source_omap2_omap3, 701}; 702 703static const struct dss_features omap34xx_dss_feats __initconst = { 704 .fck_div_max = 16, 705 .dss_fck_multiplier = 2, 706 .parent_clk_name = "dpll4_ck", 707 .dpi_select_source = &dss_dpi_select_source_omap2_omap3, 708}; 709 710static const struct dss_features omap3630_dss_feats __initconst = { 711 .fck_div_max = 32, 712 .dss_fck_multiplier = 1, 713 .parent_clk_name = "dpll4_ck", 714 .dpi_select_source = &dss_dpi_select_source_omap2_omap3, 715}; 716 717static const struct dss_features omap44xx_dss_feats __initconst = { 718 .fck_div_max = 32, 719 .dss_fck_multiplier = 1, 720 .parent_clk_name = "dpll_per_x2_ck", 721 .dpi_select_source = &dss_dpi_select_source_omap4, 722}; 723 724static const struct dss_features omap54xx_dss_feats __initconst = { 725 .fck_div_max = 64, 726 .dss_fck_multiplier = 1, 727 .parent_clk_name = "dpll_per_x2_ck", 728 .dpi_select_source = &dss_dpi_select_source_omap5, 729}; 730 731static const struct dss_features am43xx_dss_feats __initconst = { 732 .fck_div_max = 0, 733 .dss_fck_multiplier = 0, 734 .parent_clk_name = NULL, 735 .dpi_select_source = &dss_dpi_select_source_omap2_omap3, 736}; 737 738static int __init dss_init_features(struct platform_device *pdev) 739{ 740 const struct dss_features *src; 741 struct dss_features *dst; 742 743 dst = devm_kzalloc(&pdev->dev, sizeof(*dst), GFP_KERNEL); 744 if (!dst) { 745 dev_err(&pdev->dev, "Failed to allocate local DSS Features\n"); 746 return -ENOMEM; 747 } 748 749 switch (omapdss_get_version()) { 750 case OMAPDSS_VER_OMAP24xx: 751 src = &omap24xx_dss_feats; 752 break; 753 754 case OMAPDSS_VER_OMAP34xx_ES1: 755 case OMAPDSS_VER_OMAP34xx_ES3: 756 case OMAPDSS_VER_AM35xx: 757 src = &omap34xx_dss_feats; 758 break; 759 760 case OMAPDSS_VER_OMAP3630: 761 src = &omap3630_dss_feats; 762 break; 763 764 case OMAPDSS_VER_OMAP4430_ES1: 765 case OMAPDSS_VER_OMAP4430_ES2: 766 case OMAPDSS_VER_OMAP4: 767 src = &omap44xx_dss_feats; 768 break; 769 770 case OMAPDSS_VER_OMAP5: 771 src = &omap54xx_dss_feats; 772 break; 773 774 case OMAPDSS_VER_AM43xx: 775 src = &am43xx_dss_feats; 776 break; 777 778 default: 779 return -ENODEV; 780 } 781 782 memcpy(dst, src, sizeof(*dst)); 783 dss.feat = dst; 784 785 return 0; 786} 787 788static int __init dss_init_ports(struct platform_device *pdev) 789{ 790 struct device_node *parent = pdev->dev.of_node; 791 struct device_node *port; 792 int r; 793 794 if (parent == NULL) 795 return 0; 796 797 port = omapdss_of_get_next_port(parent, NULL); 798 if (!port) 799 return 0; 800 801 do { 802 u32 reg; 803 804 r = of_property_read_u32(port, "reg", ®); 805 if (r) 806 reg = 0; 807 808#ifdef CONFIG_OMAP2_DSS_DPI 809 if (reg == 0) 810 dpi_init_port(pdev, port); 811#endif 812 813#ifdef CONFIG_OMAP2_DSS_SDI 814 if (reg == 1) 815 sdi_init_port(pdev, port); 816#endif 817 818 } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); 819 820 return 0; 821} 822 823static void __exit dss_uninit_ports(void) 824{ 825#ifdef CONFIG_OMAP2_DSS_DPI 826 dpi_uninit_port(); 827#endif 828 829#ifdef CONFIG_OMAP2_DSS_SDI 830 sdi_uninit_port(); 831#endif 832} 833 834/* DSS HW IP initialisation */ 835static int __init omap_dsshw_probe(struct platform_device *pdev) 836{ 837 struct resource *dss_mem; 838 u32 rev; 839 int r; 840 841 dss.pdev = pdev; 842 843 r = dss_init_features(dss.pdev); 844 if (r) 845 return r; 846 847 dss_mem = platform_get_resource(dss.pdev, IORESOURCE_MEM, 0); 848 if (!dss_mem) { 849 DSSERR("can't get IORESOURCE_MEM DSS\n"); 850 return -EINVAL; 851 } 852 853 dss.base = devm_ioremap(&pdev->dev, dss_mem->start, 854 resource_size(dss_mem)); 855 if (!dss.base) { 856 DSSERR("can't ioremap DSS\n"); 857 return -ENOMEM; 858 } 859 860 r = dss_get_clocks(); 861 if (r) 862 return r; 863 864 r = dss_setup_default_clock(); 865 if (r) 866 goto err_setup_clocks; 867 868 pm_runtime_enable(&pdev->dev); 869 870 r = dss_runtime_get(); 871 if (r) 872 goto err_runtime_get; 873 874 dss.dss_clk_rate = clk_get_rate(dss.dss_clk); 875 876 /* Select DPLL */ 877 REG_FLD_MOD(DSS_CONTROL, 0, 0, 0); 878 879 dss_select_dispc_clk_source(OMAP_DSS_CLK_SRC_FCK); 880 881#ifdef CONFIG_OMAP2_DSS_VENC 882 REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */ 883 REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */ 884 REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */ 885#endif 886 dss.dsi_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; 887 dss.dsi_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; 888 dss.dispc_clk_source = OMAP_DSS_CLK_SRC_FCK; 889 dss.lcd_clk_source[0] = OMAP_DSS_CLK_SRC_FCK; 890 dss.lcd_clk_source[1] = OMAP_DSS_CLK_SRC_FCK; 891 892 dss_init_ports(pdev); 893 894 rev = dss_read_reg(DSS_REVISION); 895 printk(KERN_INFO "OMAP DSS rev %d.%d\n", 896 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 897 898 dss_runtime_put(); 899 900 dss_debugfs_create_file("dss", dss_dump_regs); 901 902 return 0; 903 904err_runtime_get: 905 pm_runtime_disable(&pdev->dev); 906err_setup_clocks: 907 dss_put_clocks(); 908 return r; 909} 910 911static int __exit omap_dsshw_remove(struct platform_device *pdev) 912{ 913 dss_uninit_ports(); 914 915 pm_runtime_disable(&pdev->dev); 916 917 dss_put_clocks(); 918 919 return 0; 920} 921 922static int dss_runtime_suspend(struct device *dev) 923{ 924 dss_save_context(); 925 dss_set_min_bus_tput(dev, 0); 926 return 0; 927} 928 929static int dss_runtime_resume(struct device *dev) 930{ 931 int r; 932 /* 933 * Set an arbitrarily high tput request to ensure OPP100. 934 * What we should really do is to make a request to stay in OPP100, 935 * without any tput requirements, but that is not currently possible 936 * via the PM layer. 937 */ 938 939 r = dss_set_min_bus_tput(dev, 1000000000); 940 if (r) 941 return r; 942 943 dss_restore_context(); 944 return 0; 945} 946 947static const struct dev_pm_ops dss_pm_ops = { 948 .runtime_suspend = dss_runtime_suspend, 949 .runtime_resume = dss_runtime_resume, 950}; 951 952static const struct of_device_id dss_of_match[] = { 953 { .compatible = "ti,omap2-dss", }, 954 { .compatible = "ti,omap3-dss", }, 955 { .compatible = "ti,omap4-dss", }, 956 { .compatible = "ti,omap5-dss", }, 957 {}, 958}; 959 960MODULE_DEVICE_TABLE(of, dss_of_match); 961 962static struct platform_driver omap_dsshw_driver = { 963 .remove = __exit_p(omap_dsshw_remove), 964 .driver = { 965 .name = "omapdss_dss", 966 .owner = THIS_MODULE, 967 .pm = &dss_pm_ops, 968 .of_match_table = dss_of_match, 969 .suppress_bind_attrs = true, 970 }, 971}; 972 973int __init dss_init_platform_driver(void) 974{ 975 return platform_driver_probe(&omap_dsshw_driver, omap_dsshw_probe); 976} 977 978void dss_uninit_platform_driver(void) 979{ 980 platform_driver_unregister(&omap_dsshw_driver); 981} 982