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

Configure Feed

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

at v3.3-rc2 598 lines 14 kB view raw
1/* 2 * OMAP2 Remote Frame Buffer Interface support 3 * 4 * Copyright (C) 2005 Nokia Corporation 5 * Author: Juha Yrjölä <juha.yrjola@nokia.com> 6 * Imre Deak <imre.deak@nokia.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License along 19 * with this program; if not, write to the Free Software Foundation, Inc., 20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 */ 22#include <linux/module.h> 23#include <linux/delay.h> 24#include <linux/i2c.h> 25#include <linux/err.h> 26#include <linux/interrupt.h> 27#include <linux/clk.h> 28#include <linux/io.h> 29#include <linux/platform_device.h> 30 31#include "omapfb.h" 32#include "dispc.h" 33 34/* To work around an RFBI transfer rate limitation */ 35#define OMAP_RFBI_RATE_LIMIT 1 36 37#define RFBI_BASE 0x48050800 38#define RFBI_REVISION 0x0000 39#define RFBI_SYSCONFIG 0x0010 40#define RFBI_SYSSTATUS 0x0014 41#define RFBI_CONTROL 0x0040 42#define RFBI_PIXEL_CNT 0x0044 43#define RFBI_LINE_NUMBER 0x0048 44#define RFBI_CMD 0x004c 45#define RFBI_PARAM 0x0050 46#define RFBI_DATA 0x0054 47#define RFBI_READ 0x0058 48#define RFBI_STATUS 0x005c 49#define RFBI_CONFIG0 0x0060 50#define RFBI_ONOFF_TIME0 0x0064 51#define RFBI_CYCLE_TIME0 0x0068 52#define RFBI_DATA_CYCLE1_0 0x006c 53#define RFBI_DATA_CYCLE2_0 0x0070 54#define RFBI_DATA_CYCLE3_0 0x0074 55#define RFBI_VSYNC_WIDTH 0x0090 56#define RFBI_HSYNC_WIDTH 0x0094 57 58#define DISPC_BASE 0x48050400 59#define DISPC_CONTROL 0x0040 60#define DISPC_IRQ_FRAMEMASK 0x0001 61 62static struct { 63 void __iomem *base; 64 void (*lcdc_callback)(void *data); 65 void *lcdc_callback_data; 66 unsigned long l4_khz; 67 int bits_per_cycle; 68 struct omapfb_device *fbdev; 69 struct clk *dss_ick; 70 struct clk *dss1_fck; 71 unsigned tearsync_pin_cnt; 72 unsigned tearsync_mode; 73} rfbi; 74 75static inline void rfbi_write_reg(int idx, u32 val) 76{ 77 __raw_writel(val, rfbi.base + idx); 78} 79 80static inline u32 rfbi_read_reg(int idx) 81{ 82 return __raw_readl(rfbi.base + idx); 83} 84 85static int rfbi_get_clocks(void) 86{ 87 rfbi.dss_ick = clk_get(&rfbi.fbdev->dssdev->dev, "ick"); 88 if (IS_ERR(rfbi.dss_ick)) { 89 dev_err(rfbi.fbdev->dev, "can't get ick\n"); 90 return PTR_ERR(rfbi.dss_ick); 91 } 92 93 rfbi.dss1_fck = clk_get(&rfbi.fbdev->dssdev->dev, "fck"); 94 if (IS_ERR(rfbi.dss1_fck)) { 95 dev_err(rfbi.fbdev->dev, "can't get dss1_fck\n"); 96 clk_put(rfbi.dss_ick); 97 return PTR_ERR(rfbi.dss1_fck); 98 } 99 100 return 0; 101} 102 103static void rfbi_put_clocks(void) 104{ 105 clk_put(rfbi.dss1_fck); 106 clk_put(rfbi.dss_ick); 107} 108 109static void rfbi_enable_clocks(int enable) 110{ 111 if (enable) { 112 clk_enable(rfbi.dss_ick); 113 clk_enable(rfbi.dss1_fck); 114 } else { 115 clk_disable(rfbi.dss1_fck); 116 clk_disable(rfbi.dss_ick); 117 } 118} 119 120 121#ifdef VERBOSE 122static void rfbi_print_timings(void) 123{ 124 u32 l; 125 u32 time; 126 127 l = rfbi_read_reg(RFBI_CONFIG0); 128 time = 1000000000 / rfbi.l4_khz; 129 if (l & (1 << 4)) 130 time *= 2; 131 132 dev_dbg(rfbi.fbdev->dev, "Tick time %u ps\n", time); 133 l = rfbi_read_reg(RFBI_ONOFF_TIME0); 134 dev_dbg(rfbi.fbdev->dev, 135 "CSONTIME %d, CSOFFTIME %d, WEONTIME %d, WEOFFTIME %d, " 136 "REONTIME %d, REOFFTIME %d\n", 137 l & 0x0f, (l >> 4) & 0x3f, (l >> 10) & 0x0f, (l >> 14) & 0x3f, 138 (l >> 20) & 0x0f, (l >> 24) & 0x3f); 139 140 l = rfbi_read_reg(RFBI_CYCLE_TIME0); 141 dev_dbg(rfbi.fbdev->dev, 142 "WECYCLETIME %d, RECYCLETIME %d, CSPULSEWIDTH %d, " 143 "ACCESSTIME %d\n", 144 (l & 0x3f), (l >> 6) & 0x3f, (l >> 12) & 0x3f, 145 (l >> 22) & 0x3f); 146} 147#else 148static void rfbi_print_timings(void) {} 149#endif 150 151static void rfbi_set_timings(const struct extif_timings *t) 152{ 153 u32 l; 154 155 BUG_ON(!t->converted); 156 157 rfbi_enable_clocks(1); 158 rfbi_write_reg(RFBI_ONOFF_TIME0, t->tim[0]); 159 rfbi_write_reg(RFBI_CYCLE_TIME0, t->tim[1]); 160 161 l = rfbi_read_reg(RFBI_CONFIG0); 162 l &= ~(1 << 4); 163 l |= (t->tim[2] ? 1 : 0) << 4; 164 rfbi_write_reg(RFBI_CONFIG0, l); 165 166 rfbi_print_timings(); 167 rfbi_enable_clocks(0); 168} 169 170static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div) 171{ 172 *clk_period = 1000000000 / rfbi.l4_khz; 173 *max_clk_div = 2; 174} 175 176static int ps_to_rfbi_ticks(int time, int div) 177{ 178 unsigned long tick_ps; 179 int ret; 180 181 /* Calculate in picosecs to yield more exact results */ 182 tick_ps = 1000000000 / (rfbi.l4_khz) * div; 183 184 ret = (time + tick_ps - 1) / tick_ps; 185 186 return ret; 187} 188 189#ifdef OMAP_RFBI_RATE_LIMIT 190static unsigned long rfbi_get_max_tx_rate(void) 191{ 192 unsigned long l4_rate, dss1_rate; 193 int min_l4_ticks = 0; 194 int i; 195 196 /* According to TI this can't be calculated so make the 197 * adjustments for a couple of known frequencies and warn for 198 * others. 199 */ 200 static const struct { 201 unsigned long l4_clk; /* HZ */ 202 unsigned long dss1_clk; /* HZ */ 203 unsigned long min_l4_ticks; 204 } ftab[] = { 205 { 55, 132, 7, }, /* 7.86 MPix/s */ 206 { 110, 110, 12, }, /* 9.16 MPix/s */ 207 { 110, 132, 10, }, /* 11 Mpix/s */ 208 { 120, 120, 10, }, /* 12 Mpix/s */ 209 { 133, 133, 10, }, /* 13.3 Mpix/s */ 210 }; 211 212 l4_rate = rfbi.l4_khz / 1000; 213 dss1_rate = clk_get_rate(rfbi.dss1_fck) / 1000000; 214 215 for (i = 0; i < ARRAY_SIZE(ftab); i++) { 216 /* Use a window instead of an exact match, to account 217 * for different DPLL multiplier / divider pairs. 218 */ 219 if (abs(ftab[i].l4_clk - l4_rate) < 3 && 220 abs(ftab[i].dss1_clk - dss1_rate) < 3) { 221 min_l4_ticks = ftab[i].min_l4_ticks; 222 break; 223 } 224 } 225 if (i == ARRAY_SIZE(ftab)) { 226 /* Can't be sure, return anyway the maximum not 227 * rate-limited. This might cause a problem only for the 228 * tearing synchronisation. 229 */ 230 dev_err(rfbi.fbdev->dev, 231 "can't determine maximum RFBI transfer rate\n"); 232 return rfbi.l4_khz * 1000; 233 } 234 return rfbi.l4_khz * 1000 / min_l4_ticks; 235} 236#else 237static int rfbi_get_max_tx_rate(void) 238{ 239 return rfbi.l4_khz * 1000; 240} 241#endif 242 243 244static int rfbi_convert_timings(struct extif_timings *t) 245{ 246 u32 l; 247 int reon, reoff, weon, weoff, cson, csoff, cs_pulse; 248 int actim, recyc, wecyc; 249 int div = t->clk_div; 250 251 if (div <= 0 || div > 2) 252 return -1; 253 254 /* Make sure that after conversion it still holds that: 255 * weoff > weon, reoff > reon, recyc >= reoff, wecyc >= weoff, 256 * csoff > cson, csoff >= max(weoff, reoff), actim > reon 257 */ 258 weon = ps_to_rfbi_ticks(t->we_on_time, div); 259 weoff = ps_to_rfbi_ticks(t->we_off_time, div); 260 if (weoff <= weon) 261 weoff = weon + 1; 262 if (weon > 0x0f) 263 return -1; 264 if (weoff > 0x3f) 265 return -1; 266 267 reon = ps_to_rfbi_ticks(t->re_on_time, div); 268 reoff = ps_to_rfbi_ticks(t->re_off_time, div); 269 if (reoff <= reon) 270 reoff = reon + 1; 271 if (reon > 0x0f) 272 return -1; 273 if (reoff > 0x3f) 274 return -1; 275 276 cson = ps_to_rfbi_ticks(t->cs_on_time, div); 277 csoff = ps_to_rfbi_ticks(t->cs_off_time, div); 278 if (csoff <= cson) 279 csoff = cson + 1; 280 if (csoff < max(weoff, reoff)) 281 csoff = max(weoff, reoff); 282 if (cson > 0x0f) 283 return -1; 284 if (csoff > 0x3f) 285 return -1; 286 287 l = cson; 288 l |= csoff << 4; 289 l |= weon << 10; 290 l |= weoff << 14; 291 l |= reon << 20; 292 l |= reoff << 24; 293 294 t->tim[0] = l; 295 296 actim = ps_to_rfbi_ticks(t->access_time, div); 297 if (actim <= reon) 298 actim = reon + 1; 299 if (actim > 0x3f) 300 return -1; 301 302 wecyc = ps_to_rfbi_ticks(t->we_cycle_time, div); 303 if (wecyc < weoff) 304 wecyc = weoff; 305 if (wecyc > 0x3f) 306 return -1; 307 308 recyc = ps_to_rfbi_ticks(t->re_cycle_time, div); 309 if (recyc < reoff) 310 recyc = reoff; 311 if (recyc > 0x3f) 312 return -1; 313 314 cs_pulse = ps_to_rfbi_ticks(t->cs_pulse_width, div); 315 if (cs_pulse > 0x3f) 316 return -1; 317 318 l = wecyc; 319 l |= recyc << 6; 320 l |= cs_pulse << 12; 321 l |= actim << 22; 322 323 t->tim[1] = l; 324 325 t->tim[2] = div - 1; 326 327 t->converted = 1; 328 329 return 0; 330} 331 332static int rfbi_setup_tearsync(unsigned pin_cnt, 333 unsigned hs_pulse_time, unsigned vs_pulse_time, 334 int hs_pol_inv, int vs_pol_inv, int extif_div) 335{ 336 int hs, vs; 337 int min; 338 u32 l; 339 340 if (pin_cnt != 1 && pin_cnt != 2) 341 return -EINVAL; 342 343 hs = ps_to_rfbi_ticks(hs_pulse_time, 1); 344 vs = ps_to_rfbi_ticks(vs_pulse_time, 1); 345 if (hs < 2) 346 return -EDOM; 347 if (pin_cnt == 2) 348 min = 2; 349 else 350 min = 4; 351 if (vs < min) 352 return -EDOM; 353 if (vs == hs) 354 return -EINVAL; 355 rfbi.tearsync_pin_cnt = pin_cnt; 356 dev_dbg(rfbi.fbdev->dev, 357 "setup_tearsync: pins %d hs %d vs %d hs_inv %d vs_inv %d\n", 358 pin_cnt, hs, vs, hs_pol_inv, vs_pol_inv); 359 360 rfbi_enable_clocks(1); 361 rfbi_write_reg(RFBI_HSYNC_WIDTH, hs); 362 rfbi_write_reg(RFBI_VSYNC_WIDTH, vs); 363 364 l = rfbi_read_reg(RFBI_CONFIG0); 365 if (hs_pol_inv) 366 l &= ~(1 << 21); 367 else 368 l |= 1 << 21; 369 if (vs_pol_inv) 370 l &= ~(1 << 20); 371 else 372 l |= 1 << 20; 373 rfbi_enable_clocks(0); 374 375 return 0; 376} 377 378static int rfbi_enable_tearsync(int enable, unsigned line) 379{ 380 u32 l; 381 382 dev_dbg(rfbi.fbdev->dev, "tearsync %d line %d mode %d\n", 383 enable, line, rfbi.tearsync_mode); 384 if (line > (1 << 11) - 1) 385 return -EINVAL; 386 387 rfbi_enable_clocks(1); 388 l = rfbi_read_reg(RFBI_CONFIG0); 389 l &= ~(0x3 << 2); 390 if (enable) { 391 rfbi.tearsync_mode = rfbi.tearsync_pin_cnt; 392 l |= rfbi.tearsync_mode << 2; 393 } else 394 rfbi.tearsync_mode = 0; 395 rfbi_write_reg(RFBI_CONFIG0, l); 396 rfbi_write_reg(RFBI_LINE_NUMBER, line); 397 rfbi_enable_clocks(0); 398 399 return 0; 400} 401 402static void rfbi_write_command(const void *buf, unsigned int len) 403{ 404 rfbi_enable_clocks(1); 405 if (rfbi.bits_per_cycle == 16) { 406 const u16 *w = buf; 407 BUG_ON(len & 1); 408 for (; len; len -= 2) 409 rfbi_write_reg(RFBI_CMD, *w++); 410 } else { 411 const u8 *b = buf; 412 BUG_ON(rfbi.bits_per_cycle != 8); 413 for (; len; len--) 414 rfbi_write_reg(RFBI_CMD, *b++); 415 } 416 rfbi_enable_clocks(0); 417} 418 419static void rfbi_read_data(void *buf, unsigned int len) 420{ 421 rfbi_enable_clocks(1); 422 if (rfbi.bits_per_cycle == 16) { 423 u16 *w = buf; 424 BUG_ON(len & ~1); 425 for (; len; len -= 2) { 426 rfbi_write_reg(RFBI_READ, 0); 427 *w++ = rfbi_read_reg(RFBI_READ); 428 } 429 } else { 430 u8 *b = buf; 431 BUG_ON(rfbi.bits_per_cycle != 8); 432 for (; len; len--) { 433 rfbi_write_reg(RFBI_READ, 0); 434 *b++ = rfbi_read_reg(RFBI_READ); 435 } 436 } 437 rfbi_enable_clocks(0); 438} 439 440static void rfbi_write_data(const void *buf, unsigned int len) 441{ 442 rfbi_enable_clocks(1); 443 if (rfbi.bits_per_cycle == 16) { 444 const u16 *w = buf; 445 BUG_ON(len & 1); 446 for (; len; len -= 2) 447 rfbi_write_reg(RFBI_PARAM, *w++); 448 } else { 449 const u8 *b = buf; 450 BUG_ON(rfbi.bits_per_cycle != 8); 451 for (; len; len--) 452 rfbi_write_reg(RFBI_PARAM, *b++); 453 } 454 rfbi_enable_clocks(0); 455} 456 457static void rfbi_transfer_area(int width, int height, 458 void (callback)(void * data), void *data) 459{ 460 u32 w; 461 462 BUG_ON(callback == NULL); 463 464 rfbi_enable_clocks(1); 465 omap_dispc_set_lcd_size(width, height); 466 467 rfbi.lcdc_callback = callback; 468 rfbi.lcdc_callback_data = data; 469 470 rfbi_write_reg(RFBI_PIXEL_CNT, width * height); 471 472 w = rfbi_read_reg(RFBI_CONTROL); 473 w |= 1; /* enable */ 474 if (!rfbi.tearsync_mode) 475 w |= 1 << 4; /* internal trigger, reset by HW */ 476 rfbi_write_reg(RFBI_CONTROL, w); 477 478 omap_dispc_enable_lcd_out(1); 479} 480 481static inline void _stop_transfer(void) 482{ 483 u32 w; 484 485 w = rfbi_read_reg(RFBI_CONTROL); 486 rfbi_write_reg(RFBI_CONTROL, w & ~(1 << 0)); 487 rfbi_enable_clocks(0); 488} 489 490static void rfbi_dma_callback(void *data) 491{ 492 _stop_transfer(); 493 rfbi.lcdc_callback(rfbi.lcdc_callback_data); 494} 495 496static void rfbi_set_bits_per_cycle(int bpc) 497{ 498 u32 l; 499 500 rfbi_enable_clocks(1); 501 l = rfbi_read_reg(RFBI_CONFIG0); 502 l &= ~(0x03 << 0); 503 504 switch (bpc) { 505 case 8: 506 break; 507 case 16: 508 l |= 3; 509 break; 510 default: 511 BUG(); 512 } 513 rfbi_write_reg(RFBI_CONFIG0, l); 514 rfbi.bits_per_cycle = bpc; 515 rfbi_enable_clocks(0); 516} 517 518static int rfbi_init(struct omapfb_device *fbdev) 519{ 520 u32 l; 521 int r; 522 523 rfbi.fbdev = fbdev; 524 rfbi.base = ioremap(RFBI_BASE, SZ_1K); 525 if (!rfbi.base) { 526 dev_err(fbdev->dev, "can't ioremap RFBI\n"); 527 return -ENOMEM; 528 } 529 530 if ((r = rfbi_get_clocks()) < 0) 531 return r; 532 rfbi_enable_clocks(1); 533 534 rfbi.l4_khz = clk_get_rate(rfbi.dss_ick) / 1000; 535 536 /* Reset */ 537 rfbi_write_reg(RFBI_SYSCONFIG, 1 << 1); 538 while (!(rfbi_read_reg(RFBI_SYSSTATUS) & (1 << 0))); 539 540 l = rfbi_read_reg(RFBI_SYSCONFIG); 541 /* Enable autoidle and smart-idle */ 542 l |= (1 << 0) | (2 << 3); 543 rfbi_write_reg(RFBI_SYSCONFIG, l); 544 545 /* 16-bit interface, ITE trigger mode, 16-bit data */ 546 l = (0x03 << 0) | (0x00 << 2) | (0x01 << 5) | (0x02 << 7); 547 l |= (0 << 9) | (1 << 20) | (1 << 21); 548 rfbi_write_reg(RFBI_CONFIG0, l); 549 550 rfbi_write_reg(RFBI_DATA_CYCLE1_0, 0x00000010); 551 552 l = rfbi_read_reg(RFBI_CONTROL); 553 /* Select CS0, clear bypass mode */ 554 l = (0x01 << 2); 555 rfbi_write_reg(RFBI_CONTROL, l); 556 557 r = omap_dispc_request_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, 558 NULL); 559 if (r < 0) { 560 dev_err(fbdev->dev, "can't get DISPC irq\n"); 561 rfbi_enable_clocks(0); 562 return r; 563 } 564 565 l = rfbi_read_reg(RFBI_REVISION); 566 pr_info("omapfb: RFBI version %d.%d initialized\n", 567 (l >> 4) & 0x0f, l & 0x0f); 568 569 rfbi_enable_clocks(0); 570 571 return 0; 572} 573 574static void rfbi_cleanup(void) 575{ 576 omap_dispc_free_irq(DISPC_IRQ_FRAMEMASK, rfbi_dma_callback, NULL); 577 rfbi_put_clocks(); 578 iounmap(rfbi.base); 579} 580 581const struct lcd_ctrl_extif omap2_ext_if = { 582 .init = rfbi_init, 583 .cleanup = rfbi_cleanup, 584 .get_clk_info = rfbi_get_clk_info, 585 .get_max_tx_rate = rfbi_get_max_tx_rate, 586 .set_bits_per_cycle = rfbi_set_bits_per_cycle, 587 .convert_timings = rfbi_convert_timings, 588 .set_timings = rfbi_set_timings, 589 .write_command = rfbi_write_command, 590 .read_data = rfbi_read_data, 591 .write_data = rfbi_write_data, 592 .transfer_area = rfbi_transfer_area, 593 .setup_tearsync = rfbi_setup_tearsync, 594 .enable_tearsync = rfbi_enable_tearsync, 595 596 .max_transmit_size = (u32) ~0, 597}; 598