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