Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.1 1044 lines 23 kB view raw
1/* 2 * linux/drivers/video/omap2/dss/rfbi.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 "RFBI" 24 25#include <linux/kernel.h> 26#include <linux/dma-mapping.h> 27#include <linux/vmalloc.h> 28#include <linux/clk.h> 29#include <linux/io.h> 30#include <linux/delay.h> 31#include <linux/kfifo.h> 32#include <linux/ktime.h> 33#include <linux/hrtimer.h> 34#include <linux/seq_file.h> 35#include <linux/semaphore.h> 36#include <linux/platform_device.h> 37#include <linux/pm_runtime.h> 38 39#include <video/omapdss.h> 40#include "dss.h" 41 42struct rfbi_reg { u16 idx; }; 43 44#define RFBI_REG(idx) ((const struct rfbi_reg) { idx }) 45 46#define RFBI_REVISION RFBI_REG(0x0000) 47#define RFBI_SYSCONFIG RFBI_REG(0x0010) 48#define RFBI_SYSSTATUS RFBI_REG(0x0014) 49#define RFBI_CONTROL RFBI_REG(0x0040) 50#define RFBI_PIXEL_CNT RFBI_REG(0x0044) 51#define RFBI_LINE_NUMBER RFBI_REG(0x0048) 52#define RFBI_CMD RFBI_REG(0x004c) 53#define RFBI_PARAM RFBI_REG(0x0050) 54#define RFBI_DATA RFBI_REG(0x0054) 55#define RFBI_READ RFBI_REG(0x0058) 56#define RFBI_STATUS RFBI_REG(0x005c) 57 58#define RFBI_CONFIG(n) RFBI_REG(0x0060 + (n)*0x18) 59#define RFBI_ONOFF_TIME(n) RFBI_REG(0x0064 + (n)*0x18) 60#define RFBI_CYCLE_TIME(n) RFBI_REG(0x0068 + (n)*0x18) 61#define RFBI_DATA_CYCLE1(n) RFBI_REG(0x006c + (n)*0x18) 62#define RFBI_DATA_CYCLE2(n) RFBI_REG(0x0070 + (n)*0x18) 63#define RFBI_DATA_CYCLE3(n) RFBI_REG(0x0074 + (n)*0x18) 64 65#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090) 66#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094) 67 68#define REG_FLD_MOD(idx, val, start, end) \ 69 rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end)) 70 71enum omap_rfbi_cycleformat { 72 OMAP_DSS_RFBI_CYCLEFORMAT_1_1 = 0, 73 OMAP_DSS_RFBI_CYCLEFORMAT_2_1 = 1, 74 OMAP_DSS_RFBI_CYCLEFORMAT_3_1 = 2, 75 OMAP_DSS_RFBI_CYCLEFORMAT_3_2 = 3, 76}; 77 78enum omap_rfbi_datatype { 79 OMAP_DSS_RFBI_DATATYPE_12 = 0, 80 OMAP_DSS_RFBI_DATATYPE_16 = 1, 81 OMAP_DSS_RFBI_DATATYPE_18 = 2, 82 OMAP_DSS_RFBI_DATATYPE_24 = 3, 83}; 84 85enum omap_rfbi_parallelmode { 86 OMAP_DSS_RFBI_PARALLELMODE_8 = 0, 87 OMAP_DSS_RFBI_PARALLELMODE_9 = 1, 88 OMAP_DSS_RFBI_PARALLELMODE_12 = 2, 89 OMAP_DSS_RFBI_PARALLELMODE_16 = 3, 90}; 91 92static int rfbi_convert_timings(struct rfbi_timings *t); 93static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div); 94 95static struct { 96 struct platform_device *pdev; 97 void __iomem *base; 98 99 unsigned long l4_khz; 100 101 enum omap_rfbi_datatype datatype; 102 enum omap_rfbi_parallelmode parallelmode; 103 104 enum omap_rfbi_te_mode te_mode; 105 int te_enabled; 106 107 void (*framedone_callback)(void *data); 108 void *framedone_callback_data; 109 110 struct omap_dss_device *dssdev[2]; 111 112 struct semaphore bus_lock; 113} rfbi; 114 115static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val) 116{ 117 __raw_writel(val, rfbi.base + idx.idx); 118} 119 120static inline u32 rfbi_read_reg(const struct rfbi_reg idx) 121{ 122 return __raw_readl(rfbi.base + idx.idx); 123} 124 125static int rfbi_runtime_get(void) 126{ 127 int r; 128 129 DSSDBG("rfbi_runtime_get\n"); 130 131 r = pm_runtime_get_sync(&rfbi.pdev->dev); 132 WARN_ON(r < 0); 133 return r < 0 ? r : 0; 134} 135 136static void rfbi_runtime_put(void) 137{ 138 int r; 139 140 DSSDBG("rfbi_runtime_put\n"); 141 142 r = pm_runtime_put(&rfbi.pdev->dev); 143 WARN_ON(r < 0); 144} 145 146void rfbi_bus_lock(void) 147{ 148 down(&rfbi.bus_lock); 149} 150EXPORT_SYMBOL(rfbi_bus_lock); 151 152void rfbi_bus_unlock(void) 153{ 154 up(&rfbi.bus_lock); 155} 156EXPORT_SYMBOL(rfbi_bus_unlock); 157 158void omap_rfbi_write_command(const void *buf, u32 len) 159{ 160 switch (rfbi.parallelmode) { 161 case OMAP_DSS_RFBI_PARALLELMODE_8: 162 { 163 const u8 *b = buf; 164 for (; len; len--) 165 rfbi_write_reg(RFBI_CMD, *b++); 166 break; 167 } 168 169 case OMAP_DSS_RFBI_PARALLELMODE_16: 170 { 171 const u16 *w = buf; 172 BUG_ON(len & 1); 173 for (; len; len -= 2) 174 rfbi_write_reg(RFBI_CMD, *w++); 175 break; 176 } 177 178 case OMAP_DSS_RFBI_PARALLELMODE_9: 179 case OMAP_DSS_RFBI_PARALLELMODE_12: 180 default: 181 BUG(); 182 } 183} 184EXPORT_SYMBOL(omap_rfbi_write_command); 185 186void omap_rfbi_read_data(void *buf, u32 len) 187{ 188 switch (rfbi.parallelmode) { 189 case OMAP_DSS_RFBI_PARALLELMODE_8: 190 { 191 u8 *b = buf; 192 for (; len; len--) { 193 rfbi_write_reg(RFBI_READ, 0); 194 *b++ = rfbi_read_reg(RFBI_READ); 195 } 196 break; 197 } 198 199 case OMAP_DSS_RFBI_PARALLELMODE_16: 200 { 201 u16 *w = buf; 202 BUG_ON(len & ~1); 203 for (; len; len -= 2) { 204 rfbi_write_reg(RFBI_READ, 0); 205 *w++ = rfbi_read_reg(RFBI_READ); 206 } 207 break; 208 } 209 210 case OMAP_DSS_RFBI_PARALLELMODE_9: 211 case OMAP_DSS_RFBI_PARALLELMODE_12: 212 default: 213 BUG(); 214 } 215} 216EXPORT_SYMBOL(omap_rfbi_read_data); 217 218void omap_rfbi_write_data(const void *buf, u32 len) 219{ 220 switch (rfbi.parallelmode) { 221 case OMAP_DSS_RFBI_PARALLELMODE_8: 222 { 223 const u8 *b = buf; 224 for (; len; len--) 225 rfbi_write_reg(RFBI_PARAM, *b++); 226 break; 227 } 228 229 case OMAP_DSS_RFBI_PARALLELMODE_16: 230 { 231 const u16 *w = buf; 232 BUG_ON(len & 1); 233 for (; len; len -= 2) 234 rfbi_write_reg(RFBI_PARAM, *w++); 235 break; 236 } 237 238 case OMAP_DSS_RFBI_PARALLELMODE_9: 239 case OMAP_DSS_RFBI_PARALLELMODE_12: 240 default: 241 BUG(); 242 243 } 244} 245EXPORT_SYMBOL(omap_rfbi_write_data); 246 247void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width, 248 u16 x, u16 y, 249 u16 w, u16 h) 250{ 251 int start_offset = scr_width * y + x; 252 int horiz_offset = scr_width - w; 253 int i; 254 255 if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && 256 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { 257 const u16 __iomem *pd = buf; 258 pd += start_offset; 259 260 for (; h; --h) { 261 for (i = 0; i < w; ++i) { 262 const u8 __iomem *b = (const u8 __iomem *)pd; 263 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); 264 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); 265 ++pd; 266 } 267 pd += horiz_offset; 268 } 269 } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_24 && 270 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_8) { 271 const u32 __iomem *pd = buf; 272 pd += start_offset; 273 274 for (; h; --h) { 275 for (i = 0; i < w; ++i) { 276 const u8 __iomem *b = (const u8 __iomem *)pd; 277 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+2)); 278 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+1)); 279 rfbi_write_reg(RFBI_PARAM, __raw_readb(b+0)); 280 ++pd; 281 } 282 pd += horiz_offset; 283 } 284 } else if (rfbi.datatype == OMAP_DSS_RFBI_DATATYPE_16 && 285 rfbi.parallelmode == OMAP_DSS_RFBI_PARALLELMODE_16) { 286 const u16 __iomem *pd = buf; 287 pd += start_offset; 288 289 for (; h; --h) { 290 for (i = 0; i < w; ++i) { 291 rfbi_write_reg(RFBI_PARAM, __raw_readw(pd)); 292 ++pd; 293 } 294 pd += horiz_offset; 295 } 296 } else { 297 BUG(); 298 } 299} 300EXPORT_SYMBOL(omap_rfbi_write_pixels); 301 302static void rfbi_transfer_area(struct omap_dss_device *dssdev, u16 width, 303 u16 height, void (*callback)(void *data), void *data) 304{ 305 u32 l; 306 307 /*BUG_ON(callback == 0);*/ 308 BUG_ON(rfbi.framedone_callback != NULL); 309 310 DSSDBG("rfbi_transfer_area %dx%d\n", width, height); 311 312 dispc_set_lcd_size(dssdev->manager->id, width, height); 313 314 dispc_enable_channel(dssdev->manager->id, true); 315 316 rfbi.framedone_callback = callback; 317 rfbi.framedone_callback_data = data; 318 319 rfbi_write_reg(RFBI_PIXEL_CNT, width * height); 320 321 l = rfbi_read_reg(RFBI_CONTROL); 322 l = FLD_MOD(l, 1, 0, 0); /* enable */ 323 if (!rfbi.te_enabled) 324 l = FLD_MOD(l, 1, 4, 4); /* ITE */ 325 326 rfbi_write_reg(RFBI_CONTROL, l); 327} 328 329static void framedone_callback(void *data, u32 mask) 330{ 331 void (*callback)(void *data); 332 333 DSSDBG("FRAMEDONE\n"); 334 335 REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0); 336 337 callback = rfbi.framedone_callback; 338 rfbi.framedone_callback = NULL; 339 340 if (callback != NULL) 341 callback(rfbi.framedone_callback_data); 342} 343 344#if 1 /* VERBOSE */ 345static void rfbi_print_timings(void) 346{ 347 u32 l; 348 u32 time; 349 350 l = rfbi_read_reg(RFBI_CONFIG(0)); 351 time = 1000000000 / rfbi.l4_khz; 352 if (l & (1 << 4)) 353 time *= 2; 354 355 DSSDBG("Tick time %u ps\n", time); 356 l = rfbi_read_reg(RFBI_ONOFF_TIME(0)); 357 DSSDBG("CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " 358 "REONTIME %d, REOFFTIME %d\n", 359 l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, 360 (l >> 20) & 0x0f, (l >> 24) & 0x3f); 361 362 l = rfbi_read_reg(RFBI_CYCLE_TIME(0)); 363 DSSDBG("WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " 364 "ACCESSTIME %d\n", 365 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, 366 (l >> 22) & 0x3f); 367} 368#else 369static void rfbi_print_timings(void) {} 370#endif 371 372 373 374 375static u32 extif_clk_period; 376 377static inline unsigned long round_to_extif_ticks(unsigned long ps, int div) 378{ 379 int bus_tick = extif_clk_period * div; 380 return (ps + bus_tick - 1) / bus_tick * bus_tick; 381} 382 383static int calc_reg_timing(struct rfbi_timings *t, int div) 384{ 385 t->clk_div = div; 386 387 t->cs_on_time = round_to_extif_ticks(t->cs_on_time, div); 388 389 t->we_on_time = round_to_extif_ticks(t->we_on_time, div); 390 t->we_off_time = round_to_extif_ticks(t->we_off_time, div); 391 t->we_cycle_time = round_to_extif_ticks(t->we_cycle_time, div); 392 393 t->re_on_time = round_to_extif_ticks(t->re_on_time, div); 394 t->re_off_time = round_to_extif_ticks(t->re_off_time, div); 395 t->re_cycle_time = round_to_extif_ticks(t->re_cycle_time, div); 396 397 t->access_time = round_to_extif_ticks(t->access_time, div); 398 t->cs_off_time = round_to_extif_ticks(t->cs_off_time, div); 399 t->cs_pulse_width = round_to_extif_ticks(t->cs_pulse_width, div); 400 401 DSSDBG("[reg]cson %d csoff %d reon %d reoff %d\n", 402 t->cs_on_time, t->cs_off_time, t->re_on_time, t->re_off_time); 403 DSSDBG("[reg]weon %d weoff %d recyc %d wecyc %d\n", 404 t->we_on_time, t->we_off_time, t->re_cycle_time, 405 t->we_cycle_time); 406 DSSDBG("[reg]rdaccess %d cspulse %d\n", 407 t->access_time, t->cs_pulse_width); 408 409 return rfbi_convert_timings(t); 410} 411 412static int calc_extif_timings(struct rfbi_timings *t) 413{ 414 u32 max_clk_div; 415 int div; 416 417 rfbi_get_clk_info(&extif_clk_period, &max_clk_div); 418 for (div = 1; div <= max_clk_div; div++) { 419 if (calc_reg_timing(t, div) == 0) 420 break; 421 } 422 423 if (div <= max_clk_div) 424 return 0; 425 426 DSSERR("can't setup timings\n"); 427 return -1; 428} 429 430 431static void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t) 432{ 433 int r; 434 435 if (!t->converted) { 436 r = calc_extif_timings(t); 437 if (r < 0) 438 DSSERR("Failed to calc timings\n"); 439 } 440 441 BUG_ON(!t->converted); 442 443 rfbi_write_reg(RFBI_ONOFF_TIME(rfbi_module), t->tim[0]); 444 rfbi_write_reg(RFBI_CYCLE_TIME(rfbi_module), t->tim[1]); 445 446 /* TIMEGRANULARITY */ 447 REG_FLD_MOD(RFBI_CONFIG(rfbi_module), 448 (t->tim[2] ? 1 : 0), 4, 4); 449 450 rfbi_print_timings(); 451} 452 453static int ps_to_rfbi_ticks(int time, int div) 454{ 455 unsigned long tick_ps; 456 int ret; 457 458 /* Calculate in picosecs to yield more exact results */ 459 tick_ps = 1000000000 / (rfbi.l4_khz) * div; 460 461 ret = (time + tick_ps - 1) / tick_ps; 462 463 return ret; 464} 465 466static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) 467{ 468 *clk_period = 1000000000 / rfbi.l4_khz; 469 *max_clk_div = 2; 470} 471 472static int rfbi_convert_timings(struct rfbi_timings *t) 473{ 474 u32 l; 475 int reon, reoff, weon, weoff, cson, csoff, cs_pulse; 476 int actim, recyc, wecyc; 477 int div = t->clk_div; 478 479 if (div <= 0 || div > 2) 480 return -1; 481 482 /* Make sure that after conversion it still holds that: 483 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, 484 * csoff > cson, csoff >= max(weoff, reoff), actim > reon 485 */ 486 weon = ps_to_rfbi_ticks(t->we_on_time, div); 487 weoff = ps_to_rfbi_ticks(t->we_off_time, div); 488 if (weoff <= weon) 489 weoff = weon + 1; 490 if (weon > 0x0f) 491 return -1; 492 if (weoff > 0x3f) 493 return -1; 494 495 reon = ps_to_rfbi_ticks(t->re_on_time, div); 496 reoff = ps_to_rfbi_ticks(t->re_off_time, div); 497 if (reoff <= reon) 498 reoff = reon + 1; 499 if (reon > 0x0f) 500 return -1; 501 if (reoff > 0x3f) 502 return -1; 503 504 cson = ps_to_rfbi_ticks(t->cs_on_time, div); 505 csoff = ps_to_rfbi_ticks(t->cs_off_time, div); 506 if (csoff <= cson) 507 csoff = cson + 1; 508 if (csoff < max(weoff, reoff)) 509 csoff = max(weoff, reoff); 510 if (cson > 0x0f) 511 return -1; 512 if (csoff > 0x3f) 513 return -1; 514 515 l = cson; 516 l |= csoff << 4; 517 l |= weon << 10; 518 l |= weoff << 14; 519 l |= reon << 20; 520 l |= reoff << 24; 521 522 t->tim[0] = l; 523 524 actim = ps_to_rfbi_ticks(t->access_time, div); 525 if (actim <= reon) 526 actim = reon + 1; 527 if (actim > 0x3f) 528 return -1; 529 530 wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); 531 if (wecyc < weoff) 532 wecyc = weoff; 533 if (wecyc > 0x3f) 534 return -1; 535 536 recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); 537 if (recyc < reoff) 538 recyc = reoff; 539 if (recyc > 0x3f) 540 return -1; 541 542 cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); 543 if (cs_pulse > 0x3f) 544 return -1; 545 546 l = wecyc; 547 l |= recyc << 6; 548 l |= cs_pulse << 12; 549 l |= actim << 22; 550 551 t->tim[1] = l; 552 553 t->tim[2] = div - 1; 554 555 t->converted = 1; 556 557 return 0; 558} 559 560/* xxx FIX module selection missing */ 561int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode, 562 unsigned hs_pulse_time, unsigned vs_pulse_time, 563 int hs_pol_inv, int vs_pol_inv, int extif_div) 564{ 565 int hs, vs; 566 int min; 567 u32 l; 568 569 hs = ps_to_rfbi_ticks(hs_pulse_time, 1); 570 vs = ps_to_rfbi_ticks(vs_pulse_time, 1); 571 if (hs < 2) 572 return -EDOM; 573 if (mode == OMAP_DSS_RFBI_TE_MODE_2) 574 min = 2; 575 else /* OMAP_DSS_RFBI_TE_MODE_1 */ 576 min = 4; 577 if (vs < min) 578 return -EDOM; 579 if (vs == hs) 580 return -EINVAL; 581 rfbi.te_mode = mode; 582 DSSDBG("setup_te: mode %d hs %d vs %d hs_inv %d vs_inv %d\n", 583 mode, hs, vs, hs_pol_inv, vs_pol_inv); 584 585 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); 586 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); 587 588 l = rfbi_read_reg(RFBI_CONFIG(0)); 589 if (hs_pol_inv) 590 l &= ~(1 << 21); 591 else 592 l |= 1 << 21; 593 if (vs_pol_inv) 594 l &= ~(1 << 20); 595 else 596 l |= 1 << 20; 597 598 return 0; 599} 600EXPORT_SYMBOL(omap_rfbi_setup_te); 601 602/* xxx FIX module selection missing */ 603int omap_rfbi_enable_te(bool enable, unsigned line) 604{ 605 u32 l; 606 607 DSSDBG("te %d line %d mode %d\n", enable, line, rfbi.te_mode); 608 if (line > (1 << 11) - 1) 609 return -EINVAL; 610 611 l = rfbi_read_reg(RFBI_CONFIG(0)); 612 l &= ~(0x3 << 2); 613 if (enable) { 614 rfbi.te_enabled = 1; 615 l |= rfbi.te_mode << 2; 616 } else 617 rfbi.te_enabled = 0; 618 rfbi_write_reg(RFBI_CONFIG(0), l); 619 rfbi_write_reg(RFBI_LINE_NUMBER, line); 620 621 return 0; 622} 623EXPORT_SYMBOL(omap_rfbi_enable_te); 624 625static int rfbi_configure(int rfbi_module, int bpp, int lines) 626{ 627 u32 l; 628 int cycle1 = 0, cycle2 = 0, cycle3 = 0; 629 enum omap_rfbi_cycleformat cycleformat; 630 enum omap_rfbi_datatype datatype; 631 enum omap_rfbi_parallelmode parallelmode; 632 633 switch (bpp) { 634 case 12: 635 datatype = OMAP_DSS_RFBI_DATATYPE_12; 636 break; 637 case 16: 638 datatype = OMAP_DSS_RFBI_DATATYPE_16; 639 break; 640 case 18: 641 datatype = OMAP_DSS_RFBI_DATATYPE_18; 642 break; 643 case 24: 644 datatype = OMAP_DSS_RFBI_DATATYPE_24; 645 break; 646 default: 647 BUG(); 648 return 1; 649 } 650 rfbi.datatype = datatype; 651 652 switch (lines) { 653 case 8: 654 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_8; 655 break; 656 case 9: 657 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_9; 658 break; 659 case 12: 660 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_12; 661 break; 662 case 16: 663 parallelmode = OMAP_DSS_RFBI_PARALLELMODE_16; 664 break; 665 default: 666 BUG(); 667 return 1; 668 } 669 rfbi.parallelmode = parallelmode; 670 671 if ((bpp % lines) == 0) { 672 switch (bpp / lines) { 673 case 1: 674 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_1_1; 675 break; 676 case 2: 677 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_2_1; 678 break; 679 case 3: 680 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_1; 681 break; 682 default: 683 BUG(); 684 return 1; 685 } 686 } else if ((2 * bpp % lines) == 0) { 687 if ((2 * bpp / lines) == 3) 688 cycleformat = OMAP_DSS_RFBI_CYCLEFORMAT_3_2; 689 else { 690 BUG(); 691 return 1; 692 } 693 } else { 694 BUG(); 695 return 1; 696 } 697 698 switch (cycleformat) { 699 case OMAP_DSS_RFBI_CYCLEFORMAT_1_1: 700 cycle1 = lines; 701 break; 702 703 case OMAP_DSS_RFBI_CYCLEFORMAT_2_1: 704 cycle1 = lines; 705 cycle2 = lines; 706 break; 707 708 case OMAP_DSS_RFBI_CYCLEFORMAT_3_1: 709 cycle1 = lines; 710 cycle2 = lines; 711 cycle3 = lines; 712 break; 713 714 case OMAP_DSS_RFBI_CYCLEFORMAT_3_2: 715 cycle1 = lines; 716 cycle2 = (lines / 2) | ((lines / 2) << 16); 717 cycle3 = (lines << 16); 718 break; 719 } 720 721 REG_FLD_MOD(RFBI_CONTROL, 0, 3, 2); /* clear CS */ 722 723 l = 0; 724 l |= FLD_VAL(parallelmode, 1, 0); 725 l |= FLD_VAL(0, 3, 2); /* TRIGGERMODE: ITE */ 726 l |= FLD_VAL(0, 4, 4); /* TIMEGRANULARITY */ 727 l |= FLD_VAL(datatype, 6, 5); 728 /* l |= FLD_VAL(2, 8, 7); */ /* L4FORMAT, 2pix/L4 */ 729 l |= FLD_VAL(0, 8, 7); /* L4FORMAT, 1pix/L4 */ 730 l |= FLD_VAL(cycleformat, 10, 9); 731 l |= FLD_VAL(0, 12, 11); /* UNUSEDBITS */ 732 l |= FLD_VAL(0, 16, 16); /* A0POLARITY */ 733 l |= FLD_VAL(0, 17, 17); /* REPOLARITY */ 734 l |= FLD_VAL(0, 18, 18); /* WEPOLARITY */ 735 l |= FLD_VAL(0, 19, 19); /* CSPOLARITY */ 736 l |= FLD_VAL(1, 20, 20); /* TE_VSYNC_POLARITY */ 737 l |= FLD_VAL(1, 21, 21); /* HSYNCPOLARITY */ 738 rfbi_write_reg(RFBI_CONFIG(rfbi_module), l); 739 740 rfbi_write_reg(RFBI_DATA_CYCLE1(rfbi_module), cycle1); 741 rfbi_write_reg(RFBI_DATA_CYCLE2(rfbi_module), cycle2); 742 rfbi_write_reg(RFBI_DATA_CYCLE3(rfbi_module), cycle3); 743 744 745 l = rfbi_read_reg(RFBI_CONTROL); 746 l = FLD_MOD(l, rfbi_module+1, 3, 2); /* Select CSx */ 747 l = FLD_MOD(l, 0, 1, 1); /* clear bypass */ 748 rfbi_write_reg(RFBI_CONTROL, l); 749 750 751 DSSDBG("RFBI config: bpp %d, lines %d, cycles: 0x%x 0x%x 0x%x\n", 752 bpp, lines, cycle1, cycle2, cycle3); 753 754 return 0; 755} 756 757int omap_rfbi_configure(struct omap_dss_device *dssdev, int pixel_size, 758 int data_lines) 759{ 760 return rfbi_configure(dssdev->phy.rfbi.channel, pixel_size, data_lines); 761} 762EXPORT_SYMBOL(omap_rfbi_configure); 763 764int omap_rfbi_prepare_update(struct omap_dss_device *dssdev, 765 u16 *x, u16 *y, u16 *w, u16 *h) 766{ 767 u16 dw, dh; 768 769 dssdev->driver->get_resolution(dssdev, &dw, &dh); 770 771 if (*x > dw || *y > dh) 772 return -EINVAL; 773 774 if (*x + *w > dw) 775 return -EINVAL; 776 777 if (*y + *h > dh) 778 return -EINVAL; 779 780 if (*w == 1) 781 return -EINVAL; 782 783 if (*w == 0 || *h == 0) 784 return -EINVAL; 785 786 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 787 dss_setup_partial_planes(dssdev, x, y, w, h, true); 788 dispc_set_lcd_size(dssdev->manager->id, *w, *h); 789 } 790 791 return 0; 792} 793EXPORT_SYMBOL(omap_rfbi_prepare_update); 794 795int omap_rfbi_update(struct omap_dss_device *dssdev, 796 u16 x, u16 y, u16 w, u16 h, 797 void (*callback)(void *), void *data) 798{ 799 if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) { 800 rfbi_transfer_area(dssdev, w, h, callback, data); 801 } else { 802 struct omap_overlay *ovl; 803 void __iomem *addr; 804 int scr_width; 805 806 ovl = dssdev->manager->overlays[0]; 807 scr_width = ovl->info.screen_width; 808 addr = ovl->info.vaddr; 809 810 omap_rfbi_write_pixels(addr, scr_width, x, y, w, h); 811 812 callback(data); 813 } 814 815 return 0; 816} 817EXPORT_SYMBOL(omap_rfbi_update); 818 819void rfbi_dump_regs(struct seq_file *s) 820{ 821#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, rfbi_read_reg(r)) 822 823 if (rfbi_runtime_get()) 824 return; 825 826 DUMPREG(RFBI_REVISION); 827 DUMPREG(RFBI_SYSCONFIG); 828 DUMPREG(RFBI_SYSSTATUS); 829 DUMPREG(RFBI_CONTROL); 830 DUMPREG(RFBI_PIXEL_CNT); 831 DUMPREG(RFBI_LINE_NUMBER); 832 DUMPREG(RFBI_CMD); 833 DUMPREG(RFBI_PARAM); 834 DUMPREG(RFBI_DATA); 835 DUMPREG(RFBI_READ); 836 DUMPREG(RFBI_STATUS); 837 838 DUMPREG(RFBI_CONFIG(0)); 839 DUMPREG(RFBI_ONOFF_TIME(0)); 840 DUMPREG(RFBI_CYCLE_TIME(0)); 841 DUMPREG(RFBI_DATA_CYCLE1(0)); 842 DUMPREG(RFBI_DATA_CYCLE2(0)); 843 DUMPREG(RFBI_DATA_CYCLE3(0)); 844 845 DUMPREG(RFBI_CONFIG(1)); 846 DUMPREG(RFBI_ONOFF_TIME(1)); 847 DUMPREG(RFBI_CYCLE_TIME(1)); 848 DUMPREG(RFBI_DATA_CYCLE1(1)); 849 DUMPREG(RFBI_DATA_CYCLE2(1)); 850 DUMPREG(RFBI_DATA_CYCLE3(1)); 851 852 DUMPREG(RFBI_VSYNC_WIDTH); 853 DUMPREG(RFBI_HSYNC_WIDTH); 854 855 rfbi_runtime_put(); 856#undef DUMPREG 857} 858 859int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev) 860{ 861 int r; 862 863 r = rfbi_runtime_get(); 864 if (r) 865 return r; 866 867 r = omap_dss_start_device(dssdev); 868 if (r) { 869 DSSERR("failed to start device\n"); 870 goto err0; 871 } 872 873 r = omap_dispc_register_isr(framedone_callback, NULL, 874 DISPC_IRQ_FRAMEDONE); 875 if (r) { 876 DSSERR("can't get FRAMEDONE irq\n"); 877 goto err1; 878 } 879 880 dispc_set_lcd_display_type(dssdev->manager->id, 881 OMAP_DSS_LCD_DISPLAY_TFT); 882 883 dispc_set_parallel_interface_mode(dssdev->manager->id, 884 OMAP_DSS_PARALLELMODE_RFBI); 885 886 dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size); 887 888 rfbi_configure(dssdev->phy.rfbi.channel, 889 dssdev->ctrl.pixel_size, 890 dssdev->phy.rfbi.data_lines); 891 892 rfbi_set_timings(dssdev->phy.rfbi.channel, 893 &dssdev->ctrl.rfbi_timings); 894 895 896 return 0; 897err1: 898 omap_dss_stop_device(dssdev); 899err0: 900 rfbi_runtime_put(); 901 return r; 902} 903EXPORT_SYMBOL(omapdss_rfbi_display_enable); 904 905void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) 906{ 907 omap_dispc_unregister_isr(framedone_callback, NULL, 908 DISPC_IRQ_FRAMEDONE); 909 omap_dss_stop_device(dssdev); 910 911 rfbi_runtime_put(); 912} 913EXPORT_SYMBOL(omapdss_rfbi_display_disable); 914 915int rfbi_init_display(struct omap_dss_device *dssdev) 916{ 917 rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; 918 dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; 919 return 0; 920} 921 922/* RFBI HW IP initialisation */ 923static int omap_rfbihw_probe(struct platform_device *pdev) 924{ 925 u32 rev; 926 struct resource *rfbi_mem; 927 struct clk *clk; 928 int r; 929 930 rfbi.pdev = pdev; 931 932 sema_init(&rfbi.bus_lock, 1); 933 934 rfbi_mem = platform_get_resource(rfbi.pdev, IORESOURCE_MEM, 0); 935 if (!rfbi_mem) { 936 DSSERR("can't get IORESOURCE_MEM RFBI\n"); 937 r = -EINVAL; 938 goto err_ioremap; 939 } 940 rfbi.base = ioremap(rfbi_mem->start, resource_size(rfbi_mem)); 941 if (!rfbi.base) { 942 DSSERR("can't ioremap RFBI\n"); 943 r = -ENOMEM; 944 goto err_ioremap; 945 } 946 947 pm_runtime_enable(&pdev->dev); 948 949 r = rfbi_runtime_get(); 950 if (r) 951 goto err_get_rfbi; 952 953 msleep(10); 954 955 if (cpu_is_omap24xx() || cpu_is_omap34xx() || cpu_is_omap3630()) 956 clk = dss_get_ick(); 957 else 958 clk = clk_get(&pdev->dev, "ick"); 959 if (IS_ERR(clk)) { 960 DSSERR("can't get ick\n"); 961 r = PTR_ERR(clk); 962 goto err_get_ick; 963 } 964 965 rfbi.l4_khz = clk_get_rate(clk) / 1000; 966 967 clk_put(clk); 968 969 rev = rfbi_read_reg(RFBI_REVISION); 970 dev_dbg(&pdev->dev, "OMAP RFBI rev %d.%d\n", 971 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 972 973 rfbi_runtime_put(); 974 975 return 0; 976 977err_get_ick: 978 rfbi_runtime_put(); 979err_get_rfbi: 980 pm_runtime_disable(&pdev->dev); 981 iounmap(rfbi.base); 982err_ioremap: 983 return r; 984} 985 986static int omap_rfbihw_remove(struct platform_device *pdev) 987{ 988 pm_runtime_disable(&pdev->dev); 989 iounmap(rfbi.base); 990 return 0; 991} 992 993static int rfbi_runtime_suspend(struct device *dev) 994{ 995 dispc_runtime_put(); 996 dss_runtime_put(); 997 998 return 0; 999} 1000 1001static int rfbi_runtime_resume(struct device *dev) 1002{ 1003 int r; 1004 1005 r = dss_runtime_get(); 1006 if (r < 0) 1007 goto err_get_dss; 1008 1009 r = dispc_runtime_get(); 1010 if (r < 0) 1011 goto err_get_dispc; 1012 1013 return 0; 1014 1015err_get_dispc: 1016 dss_runtime_put(); 1017err_get_dss: 1018 return r; 1019} 1020 1021static const struct dev_pm_ops rfbi_pm_ops = { 1022 .runtime_suspend = rfbi_runtime_suspend, 1023 .runtime_resume = rfbi_runtime_resume, 1024}; 1025 1026static struct platform_driver omap_rfbihw_driver = { 1027 .probe = omap_rfbihw_probe, 1028 .remove = omap_rfbihw_remove, 1029 .driver = { 1030 .name = "omapdss_rfbi", 1031 .owner = THIS_MODULE, 1032 .pm = &rfbi_pm_ops, 1033 }, 1034}; 1035 1036int rfbi_init_platform_driver(void) 1037{ 1038 return platform_driver_register(&omap_rfbihw_driver); 1039} 1040 1041void rfbi_uninit_platform_driver(void) 1042{ 1043 return platform_driver_unregister(&omap_rfbihw_driver); 1044}