1/* 2 * linux/drivers/video/omap2/dss/dispc.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 "DISPC" 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/jiffies.h> 31#include <linux/seq_file.h> 32#include <linux/delay.h> 33#include <linux/workqueue.h> 34#include <linux/hardirq.h> 35 36#include <plat/sram.h> 37#include <plat/clock.h> 38 39#include <plat/display.h> 40 41#include "dss.h" 42 43/* DISPC */ 44#define DISPC_BASE 0x48050400 45 46#define DISPC_SZ_REGS SZ_1K 47 48struct dispc_reg { u16 idx; }; 49 50#define DISPC_REG(idx) ((const struct dispc_reg) { idx }) 51 52/* DISPC common */ 53#define DISPC_REVISION DISPC_REG(0x0000) 54#define DISPC_SYSCONFIG DISPC_REG(0x0010) 55#define DISPC_SYSSTATUS DISPC_REG(0x0014) 56#define DISPC_IRQSTATUS DISPC_REG(0x0018) 57#define DISPC_IRQENABLE DISPC_REG(0x001C) 58#define DISPC_CONTROL DISPC_REG(0x0040) 59#define DISPC_CONFIG DISPC_REG(0x0044) 60#define DISPC_CAPABLE DISPC_REG(0x0048) 61#define DISPC_DEFAULT_COLOR0 DISPC_REG(0x004C) 62#define DISPC_DEFAULT_COLOR1 DISPC_REG(0x0050) 63#define DISPC_TRANS_COLOR0 DISPC_REG(0x0054) 64#define DISPC_TRANS_COLOR1 DISPC_REG(0x0058) 65#define DISPC_LINE_STATUS DISPC_REG(0x005C) 66#define DISPC_LINE_NUMBER DISPC_REG(0x0060) 67#define DISPC_TIMING_H DISPC_REG(0x0064) 68#define DISPC_TIMING_V DISPC_REG(0x0068) 69#define DISPC_POL_FREQ DISPC_REG(0x006C) 70#define DISPC_DIVISOR DISPC_REG(0x0070) 71#define DISPC_GLOBAL_ALPHA DISPC_REG(0x0074) 72#define DISPC_SIZE_DIG DISPC_REG(0x0078) 73#define DISPC_SIZE_LCD DISPC_REG(0x007C) 74 75/* DISPC GFX plane */ 76#define DISPC_GFX_BA0 DISPC_REG(0x0080) 77#define DISPC_GFX_BA1 DISPC_REG(0x0084) 78#define DISPC_GFX_POSITION DISPC_REG(0x0088) 79#define DISPC_GFX_SIZE DISPC_REG(0x008C) 80#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0) 81#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4) 82#define DISPC_GFX_FIFO_SIZE_STATUS DISPC_REG(0x00A8) 83#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC) 84#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0) 85#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4) 86#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8) 87 88#define DISPC_DATA_CYCLE1 DISPC_REG(0x01D4) 89#define DISPC_DATA_CYCLE2 DISPC_REG(0x01D8) 90#define DISPC_DATA_CYCLE3 DISPC_REG(0x01DC) 91 92#define DISPC_CPR_COEF_R DISPC_REG(0x0220) 93#define DISPC_CPR_COEF_G DISPC_REG(0x0224) 94#define DISPC_CPR_COEF_B DISPC_REG(0x0228) 95 96#define DISPC_GFX_PRELOAD DISPC_REG(0x022C) 97 98/* DISPC Video plane, n = 0 for VID1 and n = 1 for VID2 */ 99#define DISPC_VID_REG(n, idx) DISPC_REG(0x00BC + (n)*0x90 + idx) 100 101#define DISPC_VID_BA0(n) DISPC_VID_REG(n, 0x0000) 102#define DISPC_VID_BA1(n) DISPC_VID_REG(n, 0x0004) 103#define DISPC_VID_POSITION(n) DISPC_VID_REG(n, 0x0008) 104#define DISPC_VID_SIZE(n) DISPC_VID_REG(n, 0x000C) 105#define DISPC_VID_ATTRIBUTES(n) DISPC_VID_REG(n, 0x0010) 106#define DISPC_VID_FIFO_THRESHOLD(n) DISPC_VID_REG(n, 0x0014) 107#define DISPC_VID_FIFO_SIZE_STATUS(n) DISPC_VID_REG(n, 0x0018) 108#define DISPC_VID_ROW_INC(n) DISPC_VID_REG(n, 0x001C) 109#define DISPC_VID_PIXEL_INC(n) DISPC_VID_REG(n, 0x0020) 110#define DISPC_VID_FIR(n) DISPC_VID_REG(n, 0x0024) 111#define DISPC_VID_PICTURE_SIZE(n) DISPC_VID_REG(n, 0x0028) 112#define DISPC_VID_ACCU0(n) DISPC_VID_REG(n, 0x002C) 113#define DISPC_VID_ACCU1(n) DISPC_VID_REG(n, 0x0030) 114 115/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ 116#define DISPC_VID_FIR_COEF_H(n, i) DISPC_REG(0x00F0 + (n)*0x90 + (i)*0x8) 117/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ 118#define DISPC_VID_FIR_COEF_HV(n, i) DISPC_REG(0x00F4 + (n)*0x90 + (i)*0x8) 119/* coef index i = {0, 1, 2, 3, 4} */ 120#define DISPC_VID_CONV_COEF(n, i) DISPC_REG(0x0130 + (n)*0x90 + (i)*0x4) 121/* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ 122#define DISPC_VID_FIR_COEF_V(n, i) DISPC_REG(0x01E0 + (n)*0x20 + (i)*0x4) 123 124#define DISPC_VID_PRELOAD(n) DISPC_REG(0x230 + (n)*0x04) 125 126 127#define DISPC_IRQ_MASK_ERROR (DISPC_IRQ_GFX_FIFO_UNDERFLOW | \ 128 DISPC_IRQ_OCP_ERR | \ 129 DISPC_IRQ_VID1_FIFO_UNDERFLOW | \ 130 DISPC_IRQ_VID2_FIFO_UNDERFLOW | \ 131 DISPC_IRQ_SYNC_LOST | \ 132 DISPC_IRQ_SYNC_LOST_DIGIT) 133 134#define DISPC_MAX_NR_ISRS 8 135 136struct omap_dispc_isr_data { 137 omap_dispc_isr_t isr; 138 void *arg; 139 u32 mask; 140}; 141 142#define REG_GET(idx, start, end) \ 143 FLD_GET(dispc_read_reg(idx), start, end) 144 145#define REG_FLD_MOD(idx, val, start, end) \ 146 dispc_write_reg(idx, FLD_MOD(dispc_read_reg(idx), val, start, end)) 147 148static const struct dispc_reg dispc_reg_att[] = { DISPC_GFX_ATTRIBUTES, 149 DISPC_VID_ATTRIBUTES(0), 150 DISPC_VID_ATTRIBUTES(1) }; 151 152struct dispc_irq_stats { 153 unsigned long last_reset; 154 unsigned irq_count; 155 unsigned irqs[32]; 156}; 157 158static struct { 159 void __iomem *base; 160 161 u32 fifo_size[3]; 162 163 spinlock_t irq_lock; 164 u32 irq_error_mask; 165 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; 166 u32 error_irqs; 167 struct work_struct error_work; 168 169 u32 ctx[DISPC_SZ_REGS / sizeof(u32)]; 170 171#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 172 spinlock_t irq_stats_lock; 173 struct dispc_irq_stats irq_stats; 174#endif 175} dispc; 176 177static void _omap_dispc_set_irqs(void); 178 179static inline void dispc_write_reg(const struct dispc_reg idx, u32 val) 180{ 181 __raw_writel(val, dispc.base + idx.idx); 182} 183 184static inline u32 dispc_read_reg(const struct dispc_reg idx) 185{ 186 return __raw_readl(dispc.base + idx.idx); 187} 188 189#define SR(reg) \ 190 dispc.ctx[(DISPC_##reg).idx / sizeof(u32)] = dispc_read_reg(DISPC_##reg) 191#define RR(reg) \ 192 dispc_write_reg(DISPC_##reg, dispc.ctx[(DISPC_##reg).idx / sizeof(u32)]) 193 194void dispc_save_context(void) 195{ 196 if (cpu_is_omap24xx()) 197 return; 198 199 SR(SYSCONFIG); 200 SR(IRQENABLE); 201 SR(CONTROL); 202 SR(CONFIG); 203 SR(DEFAULT_COLOR0); 204 SR(DEFAULT_COLOR1); 205 SR(TRANS_COLOR0); 206 SR(TRANS_COLOR1); 207 SR(LINE_NUMBER); 208 SR(TIMING_H); 209 SR(TIMING_V); 210 SR(POL_FREQ); 211 SR(DIVISOR); 212 SR(GLOBAL_ALPHA); 213 SR(SIZE_DIG); 214 SR(SIZE_LCD); 215 216 SR(GFX_BA0); 217 SR(GFX_BA1); 218 SR(GFX_POSITION); 219 SR(GFX_SIZE); 220 SR(GFX_ATTRIBUTES); 221 SR(GFX_FIFO_THRESHOLD); 222 SR(GFX_ROW_INC); 223 SR(GFX_PIXEL_INC); 224 SR(GFX_WINDOW_SKIP); 225 SR(GFX_TABLE_BA); 226 227 SR(DATA_CYCLE1); 228 SR(DATA_CYCLE2); 229 SR(DATA_CYCLE3); 230 231 SR(CPR_COEF_R); 232 SR(CPR_COEF_G); 233 SR(CPR_COEF_B); 234 235 SR(GFX_PRELOAD); 236 237 /* VID1 */ 238 SR(VID_BA0(0)); 239 SR(VID_BA1(0)); 240 SR(VID_POSITION(0)); 241 SR(VID_SIZE(0)); 242 SR(VID_ATTRIBUTES(0)); 243 SR(VID_FIFO_THRESHOLD(0)); 244 SR(VID_ROW_INC(0)); 245 SR(VID_PIXEL_INC(0)); 246 SR(VID_FIR(0)); 247 SR(VID_PICTURE_SIZE(0)); 248 SR(VID_ACCU0(0)); 249 SR(VID_ACCU1(0)); 250 251 SR(VID_FIR_COEF_H(0, 0)); 252 SR(VID_FIR_COEF_H(0, 1)); 253 SR(VID_FIR_COEF_H(0, 2)); 254 SR(VID_FIR_COEF_H(0, 3)); 255 SR(VID_FIR_COEF_H(0, 4)); 256 SR(VID_FIR_COEF_H(0, 5)); 257 SR(VID_FIR_COEF_H(0, 6)); 258 SR(VID_FIR_COEF_H(0, 7)); 259 260 SR(VID_FIR_COEF_HV(0, 0)); 261 SR(VID_FIR_COEF_HV(0, 1)); 262 SR(VID_FIR_COEF_HV(0, 2)); 263 SR(VID_FIR_COEF_HV(0, 3)); 264 SR(VID_FIR_COEF_HV(0, 4)); 265 SR(VID_FIR_COEF_HV(0, 5)); 266 SR(VID_FIR_COEF_HV(0, 6)); 267 SR(VID_FIR_COEF_HV(0, 7)); 268 269 SR(VID_CONV_COEF(0, 0)); 270 SR(VID_CONV_COEF(0, 1)); 271 SR(VID_CONV_COEF(0, 2)); 272 SR(VID_CONV_COEF(0, 3)); 273 SR(VID_CONV_COEF(0, 4)); 274 275 SR(VID_FIR_COEF_V(0, 0)); 276 SR(VID_FIR_COEF_V(0, 1)); 277 SR(VID_FIR_COEF_V(0, 2)); 278 SR(VID_FIR_COEF_V(0, 3)); 279 SR(VID_FIR_COEF_V(0, 4)); 280 SR(VID_FIR_COEF_V(0, 5)); 281 SR(VID_FIR_COEF_V(0, 6)); 282 SR(VID_FIR_COEF_V(0, 7)); 283 284 SR(VID_PRELOAD(0)); 285 286 /* VID2 */ 287 SR(VID_BA0(1)); 288 SR(VID_BA1(1)); 289 SR(VID_POSITION(1)); 290 SR(VID_SIZE(1)); 291 SR(VID_ATTRIBUTES(1)); 292 SR(VID_FIFO_THRESHOLD(1)); 293 SR(VID_ROW_INC(1)); 294 SR(VID_PIXEL_INC(1)); 295 SR(VID_FIR(1)); 296 SR(VID_PICTURE_SIZE(1)); 297 SR(VID_ACCU0(1)); 298 SR(VID_ACCU1(1)); 299 300 SR(VID_FIR_COEF_H(1, 0)); 301 SR(VID_FIR_COEF_H(1, 1)); 302 SR(VID_FIR_COEF_H(1, 2)); 303 SR(VID_FIR_COEF_H(1, 3)); 304 SR(VID_FIR_COEF_H(1, 4)); 305 SR(VID_FIR_COEF_H(1, 5)); 306 SR(VID_FIR_COEF_H(1, 6)); 307 SR(VID_FIR_COEF_H(1, 7)); 308 309 SR(VID_FIR_COEF_HV(1, 0)); 310 SR(VID_FIR_COEF_HV(1, 1)); 311 SR(VID_FIR_COEF_HV(1, 2)); 312 SR(VID_FIR_COEF_HV(1, 3)); 313 SR(VID_FIR_COEF_HV(1, 4)); 314 SR(VID_FIR_COEF_HV(1, 5)); 315 SR(VID_FIR_COEF_HV(1, 6)); 316 SR(VID_FIR_COEF_HV(1, 7)); 317 318 SR(VID_CONV_COEF(1, 0)); 319 SR(VID_CONV_COEF(1, 1)); 320 SR(VID_CONV_COEF(1, 2)); 321 SR(VID_CONV_COEF(1, 3)); 322 SR(VID_CONV_COEF(1, 4)); 323 324 SR(VID_FIR_COEF_V(1, 0)); 325 SR(VID_FIR_COEF_V(1, 1)); 326 SR(VID_FIR_COEF_V(1, 2)); 327 SR(VID_FIR_COEF_V(1, 3)); 328 SR(VID_FIR_COEF_V(1, 4)); 329 SR(VID_FIR_COEF_V(1, 5)); 330 SR(VID_FIR_COEF_V(1, 6)); 331 SR(VID_FIR_COEF_V(1, 7)); 332 333 SR(VID_PRELOAD(1)); 334} 335 336void dispc_restore_context(void) 337{ 338 RR(SYSCONFIG); 339 /*RR(IRQENABLE);*/ 340 /*RR(CONTROL);*/ 341 RR(CONFIG); 342 RR(DEFAULT_COLOR0); 343 RR(DEFAULT_COLOR1); 344 RR(TRANS_COLOR0); 345 RR(TRANS_COLOR1); 346 RR(LINE_NUMBER); 347 RR(TIMING_H); 348 RR(TIMING_V); 349 RR(POL_FREQ); 350 RR(DIVISOR); 351 RR(GLOBAL_ALPHA); 352 RR(SIZE_DIG); 353 RR(SIZE_LCD); 354 355 RR(GFX_BA0); 356 RR(GFX_BA1); 357 RR(GFX_POSITION); 358 RR(GFX_SIZE); 359 RR(GFX_ATTRIBUTES); 360 RR(GFX_FIFO_THRESHOLD); 361 RR(GFX_ROW_INC); 362 RR(GFX_PIXEL_INC); 363 RR(GFX_WINDOW_SKIP); 364 RR(GFX_TABLE_BA); 365 366 RR(DATA_CYCLE1); 367 RR(DATA_CYCLE2); 368 RR(DATA_CYCLE3); 369 370 RR(CPR_COEF_R); 371 RR(CPR_COEF_G); 372 RR(CPR_COEF_B); 373 374 RR(GFX_PRELOAD); 375 376 /* VID1 */ 377 RR(VID_BA0(0)); 378 RR(VID_BA1(0)); 379 RR(VID_POSITION(0)); 380 RR(VID_SIZE(0)); 381 RR(VID_ATTRIBUTES(0)); 382 RR(VID_FIFO_THRESHOLD(0)); 383 RR(VID_ROW_INC(0)); 384 RR(VID_PIXEL_INC(0)); 385 RR(VID_FIR(0)); 386 RR(VID_PICTURE_SIZE(0)); 387 RR(VID_ACCU0(0)); 388 RR(VID_ACCU1(0)); 389 390 RR(VID_FIR_COEF_H(0, 0)); 391 RR(VID_FIR_COEF_H(0, 1)); 392 RR(VID_FIR_COEF_H(0, 2)); 393 RR(VID_FIR_COEF_H(0, 3)); 394 RR(VID_FIR_COEF_H(0, 4)); 395 RR(VID_FIR_COEF_H(0, 5)); 396 RR(VID_FIR_COEF_H(0, 6)); 397 RR(VID_FIR_COEF_H(0, 7)); 398 399 RR(VID_FIR_COEF_HV(0, 0)); 400 RR(VID_FIR_COEF_HV(0, 1)); 401 RR(VID_FIR_COEF_HV(0, 2)); 402 RR(VID_FIR_COEF_HV(0, 3)); 403 RR(VID_FIR_COEF_HV(0, 4)); 404 RR(VID_FIR_COEF_HV(0, 5)); 405 RR(VID_FIR_COEF_HV(0, 6)); 406 RR(VID_FIR_COEF_HV(0, 7)); 407 408 RR(VID_CONV_COEF(0, 0)); 409 RR(VID_CONV_COEF(0, 1)); 410 RR(VID_CONV_COEF(0, 2)); 411 RR(VID_CONV_COEF(0, 3)); 412 RR(VID_CONV_COEF(0, 4)); 413 414 RR(VID_FIR_COEF_V(0, 0)); 415 RR(VID_FIR_COEF_V(0, 1)); 416 RR(VID_FIR_COEF_V(0, 2)); 417 RR(VID_FIR_COEF_V(0, 3)); 418 RR(VID_FIR_COEF_V(0, 4)); 419 RR(VID_FIR_COEF_V(0, 5)); 420 RR(VID_FIR_COEF_V(0, 6)); 421 RR(VID_FIR_COEF_V(0, 7)); 422 423 RR(VID_PRELOAD(0)); 424 425 /* VID2 */ 426 RR(VID_BA0(1)); 427 RR(VID_BA1(1)); 428 RR(VID_POSITION(1)); 429 RR(VID_SIZE(1)); 430 RR(VID_ATTRIBUTES(1)); 431 RR(VID_FIFO_THRESHOLD(1)); 432 RR(VID_ROW_INC(1)); 433 RR(VID_PIXEL_INC(1)); 434 RR(VID_FIR(1)); 435 RR(VID_PICTURE_SIZE(1)); 436 RR(VID_ACCU0(1)); 437 RR(VID_ACCU1(1)); 438 439 RR(VID_FIR_COEF_H(1, 0)); 440 RR(VID_FIR_COEF_H(1, 1)); 441 RR(VID_FIR_COEF_H(1, 2)); 442 RR(VID_FIR_COEF_H(1, 3)); 443 RR(VID_FIR_COEF_H(1, 4)); 444 RR(VID_FIR_COEF_H(1, 5)); 445 RR(VID_FIR_COEF_H(1, 6)); 446 RR(VID_FIR_COEF_H(1, 7)); 447 448 RR(VID_FIR_COEF_HV(1, 0)); 449 RR(VID_FIR_COEF_HV(1, 1)); 450 RR(VID_FIR_COEF_HV(1, 2)); 451 RR(VID_FIR_COEF_HV(1, 3)); 452 RR(VID_FIR_COEF_HV(1, 4)); 453 RR(VID_FIR_COEF_HV(1, 5)); 454 RR(VID_FIR_COEF_HV(1, 6)); 455 RR(VID_FIR_COEF_HV(1, 7)); 456 457 RR(VID_CONV_COEF(1, 0)); 458 RR(VID_CONV_COEF(1, 1)); 459 RR(VID_CONV_COEF(1, 2)); 460 RR(VID_CONV_COEF(1, 3)); 461 RR(VID_CONV_COEF(1, 4)); 462 463 RR(VID_FIR_COEF_V(1, 0)); 464 RR(VID_FIR_COEF_V(1, 1)); 465 RR(VID_FIR_COEF_V(1, 2)); 466 RR(VID_FIR_COEF_V(1, 3)); 467 RR(VID_FIR_COEF_V(1, 4)); 468 RR(VID_FIR_COEF_V(1, 5)); 469 RR(VID_FIR_COEF_V(1, 6)); 470 RR(VID_FIR_COEF_V(1, 7)); 471 472 RR(VID_PRELOAD(1)); 473 474 /* enable last, because LCD & DIGIT enable are here */ 475 RR(CONTROL); 476 477 /* clear spurious SYNC_LOST_DIGIT interrupts */ 478 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); 479 480 /* 481 * enable last so IRQs won't trigger before 482 * the context is fully restored 483 */ 484 RR(IRQENABLE); 485} 486 487#undef SR 488#undef RR 489 490static inline void enable_clocks(bool enable) 491{ 492 if (enable) 493 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 494 else 495 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 496} 497 498bool dispc_go_busy(enum omap_channel channel) 499{ 500 int bit; 501 502 if (channel == OMAP_DSS_CHANNEL_LCD) 503 bit = 5; /* GOLCD */ 504 else 505 bit = 6; /* GODIGIT */ 506 507 return REG_GET(DISPC_CONTROL, bit, bit) == 1; 508} 509 510void dispc_go(enum omap_channel channel) 511{ 512 int bit; 513 514 enable_clocks(1); 515 516 if (channel == OMAP_DSS_CHANNEL_LCD) 517 bit = 0; /* LCDENABLE */ 518 else 519 bit = 1; /* DIGITALENABLE */ 520 521 /* if the channel is not enabled, we don't need GO */ 522 if (REG_GET(DISPC_CONTROL, bit, bit) == 0) 523 goto end; 524 525 if (channel == OMAP_DSS_CHANNEL_LCD) 526 bit = 5; /* GOLCD */ 527 else 528 bit = 6; /* GODIGIT */ 529 530 if (REG_GET(DISPC_CONTROL, bit, bit) == 1) { 531 DSSERR("GO bit not down for channel %d\n", channel); 532 goto end; 533 } 534 535 DSSDBG("GO %s\n", channel == OMAP_DSS_CHANNEL_LCD ? "LCD" : "DIGIT"); 536 537 REG_FLD_MOD(DISPC_CONTROL, 1, bit, bit); 538end: 539 enable_clocks(0); 540} 541 542static void _dispc_write_firh_reg(enum omap_plane plane, int reg, u32 value) 543{ 544 BUG_ON(plane == OMAP_DSS_GFX); 545 546 dispc_write_reg(DISPC_VID_FIR_COEF_H(plane-1, reg), value); 547} 548 549static void _dispc_write_firhv_reg(enum omap_plane plane, int reg, u32 value) 550{ 551 BUG_ON(plane == OMAP_DSS_GFX); 552 553 dispc_write_reg(DISPC_VID_FIR_COEF_HV(plane-1, reg), value); 554} 555 556static void _dispc_write_firv_reg(enum omap_plane plane, int reg, u32 value) 557{ 558 BUG_ON(plane == OMAP_DSS_GFX); 559 560 dispc_write_reg(DISPC_VID_FIR_COEF_V(plane-1, reg), value); 561} 562 563static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup, 564 int vscaleup, int five_taps) 565{ 566 /* Coefficients for horizontal up-sampling */ 567 static const u32 coef_hup[8] = { 568 0x00800000, 569 0x0D7CF800, 570 0x1E70F5FF, 571 0x335FF5FE, 572 0xF74949F7, 573 0xF55F33FB, 574 0xF5701EFE, 575 0xF87C0DFF, 576 }; 577 578 /* Coefficients for horizontal down-sampling */ 579 static const u32 coef_hdown[8] = { 580 0x24382400, 581 0x28371FFE, 582 0x2C361BFB, 583 0x303516F9, 584 0x11343311, 585 0x1635300C, 586 0x1B362C08, 587 0x1F372804, 588 }; 589 590 /* Coefficients for horizontal and vertical up-sampling */ 591 static const u32 coef_hvup[2][8] = { 592 { 593 0x00800000, 594 0x037B02FF, 595 0x0C6F05FE, 596 0x205907FB, 597 0x00404000, 598 0x075920FE, 599 0x056F0CFF, 600 0x027B0300, 601 }, 602 { 603 0x00800000, 604 0x0D7CF8FF, 605 0x1E70F5FE, 606 0x335FF5FB, 607 0xF7404000, 608 0xF55F33FE, 609 0xF5701EFF, 610 0xF87C0D00, 611 }, 612 }; 613 614 /* Coefficients for horizontal and vertical down-sampling */ 615 static const u32 coef_hvdown[2][8] = { 616 { 617 0x24382400, 618 0x28391F04, 619 0x2D381B08, 620 0x3237170C, 621 0x123737F7, 622 0x173732F9, 623 0x1B382DFB, 624 0x1F3928FE, 625 }, 626 { 627 0x24382400, 628 0x28371F04, 629 0x2C361B08, 630 0x3035160C, 631 0x113433F7, 632 0x163530F9, 633 0x1B362CFB, 634 0x1F3728FE, 635 }, 636 }; 637 638 /* Coefficients for vertical up-sampling */ 639 static const u32 coef_vup[8] = { 640 0x00000000, 641 0x0000FF00, 642 0x0000FEFF, 643 0x0000FBFE, 644 0x000000F7, 645 0x0000FEFB, 646 0x0000FFFE, 647 0x000000FF, 648 }; 649 650 651 /* Coefficients for vertical down-sampling */ 652 static const u32 coef_vdown[8] = { 653 0x00000000, 654 0x000004FE, 655 0x000008FB, 656 0x00000CF9, 657 0x0000F711, 658 0x0000F90C, 659 0x0000FB08, 660 0x0000FE04, 661 }; 662 663 const u32 *h_coef; 664 const u32 *hv_coef; 665 const u32 *hv_coef_mod; 666 const u32 *v_coef; 667 int i; 668 669 if (hscaleup) 670 h_coef = coef_hup; 671 else 672 h_coef = coef_hdown; 673 674 if (vscaleup) { 675 hv_coef = coef_hvup[five_taps]; 676 v_coef = coef_vup; 677 678 if (hscaleup) 679 hv_coef_mod = NULL; 680 else 681 hv_coef_mod = coef_hvdown[five_taps]; 682 } else { 683 hv_coef = coef_hvdown[five_taps]; 684 v_coef = coef_vdown; 685 686 if (hscaleup) 687 hv_coef_mod = coef_hvup[five_taps]; 688 else 689 hv_coef_mod = NULL; 690 } 691 692 for (i = 0; i < 8; i++) { 693 u32 h, hv; 694 695 h = h_coef[i]; 696 697 hv = hv_coef[i]; 698 699 if (hv_coef_mod) { 700 hv &= 0xffffff00; 701 hv |= (hv_coef_mod[i] & 0xff); 702 } 703 704 _dispc_write_firh_reg(plane, i, h); 705 _dispc_write_firhv_reg(plane, i, hv); 706 } 707 708 if (!five_taps) 709 return; 710 711 for (i = 0; i < 8; i++) { 712 u32 v; 713 v = v_coef[i]; 714 _dispc_write_firv_reg(plane, i, v); 715 } 716} 717 718static void _dispc_setup_color_conv_coef(void) 719{ 720 const struct color_conv_coef { 721 int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; 722 int full_range; 723 } ctbl_bt601_5 = { 724 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, 725 }; 726 727 const struct color_conv_coef *ct; 728 729#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) 730 731 ct = &ctbl_bt601_5; 732 733 dispc_write_reg(DISPC_VID_CONV_COEF(0, 0), CVAL(ct->rcr, ct->ry)); 734 dispc_write_reg(DISPC_VID_CONV_COEF(0, 1), CVAL(ct->gy, ct->rcb)); 735 dispc_write_reg(DISPC_VID_CONV_COEF(0, 2), CVAL(ct->gcb, ct->gcr)); 736 dispc_write_reg(DISPC_VID_CONV_COEF(0, 3), CVAL(ct->bcr, ct->by)); 737 dispc_write_reg(DISPC_VID_CONV_COEF(0, 4), CVAL(0, ct->bcb)); 738 739 dispc_write_reg(DISPC_VID_CONV_COEF(1, 0), CVAL(ct->rcr, ct->ry)); 740 dispc_write_reg(DISPC_VID_CONV_COEF(1, 1), CVAL(ct->gy, ct->rcb)); 741 dispc_write_reg(DISPC_VID_CONV_COEF(1, 2), CVAL(ct->gcb, ct->gcr)); 742 dispc_write_reg(DISPC_VID_CONV_COEF(1, 3), CVAL(ct->bcr, ct->by)); 743 dispc_write_reg(DISPC_VID_CONV_COEF(1, 4), CVAL(0, ct->bcb)); 744 745#undef CVAL 746 747 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(0), ct->full_range, 11, 11); 748 REG_FLD_MOD(DISPC_VID_ATTRIBUTES(1), ct->full_range, 11, 11); 749} 750 751 752static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr) 753{ 754 const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0, 755 DISPC_VID_BA0(0), 756 DISPC_VID_BA0(1) }; 757 758 dispc_write_reg(ba0_reg[plane], paddr); 759} 760 761static void _dispc_set_plane_ba1(enum omap_plane plane, u32 paddr) 762{ 763 const struct dispc_reg ba1_reg[] = { DISPC_GFX_BA1, 764 DISPC_VID_BA1(0), 765 DISPC_VID_BA1(1) }; 766 767 dispc_write_reg(ba1_reg[plane], paddr); 768} 769 770static void _dispc_set_plane_pos(enum omap_plane plane, int x, int y) 771{ 772 const struct dispc_reg pos_reg[] = { DISPC_GFX_POSITION, 773 DISPC_VID_POSITION(0), 774 DISPC_VID_POSITION(1) }; 775 776 u32 val = FLD_VAL(y, 26, 16) | FLD_VAL(x, 10, 0); 777 dispc_write_reg(pos_reg[plane], val); 778} 779 780static void _dispc_set_pic_size(enum omap_plane plane, int width, int height) 781{ 782 const struct dispc_reg siz_reg[] = { DISPC_GFX_SIZE, 783 DISPC_VID_PICTURE_SIZE(0), 784 DISPC_VID_PICTURE_SIZE(1) }; 785 u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 786 dispc_write_reg(siz_reg[plane], val); 787} 788 789static void _dispc_set_vid_size(enum omap_plane plane, int width, int height) 790{ 791 u32 val; 792 const struct dispc_reg vsi_reg[] = { DISPC_VID_SIZE(0), 793 DISPC_VID_SIZE(1) }; 794 795 BUG_ON(plane == OMAP_DSS_GFX); 796 797 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 798 dispc_write_reg(vsi_reg[plane-1], val); 799} 800 801static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha) 802{ 803 804 BUG_ON(plane == OMAP_DSS_VIDEO1); 805 806 if (cpu_is_omap24xx()) 807 return; 808 809 if (plane == OMAP_DSS_GFX) 810 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0); 811 else if (plane == OMAP_DSS_VIDEO2) 812 REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 23, 16); 813} 814 815static void _dispc_set_pix_inc(enum omap_plane plane, s32 inc) 816{ 817 const struct dispc_reg ri_reg[] = { DISPC_GFX_PIXEL_INC, 818 DISPC_VID_PIXEL_INC(0), 819 DISPC_VID_PIXEL_INC(1) }; 820 821 dispc_write_reg(ri_reg[plane], inc); 822} 823 824static void _dispc_set_row_inc(enum omap_plane plane, s32 inc) 825{ 826 const struct dispc_reg ri_reg[] = { DISPC_GFX_ROW_INC, 827 DISPC_VID_ROW_INC(0), 828 DISPC_VID_ROW_INC(1) }; 829 830 dispc_write_reg(ri_reg[plane], inc); 831} 832 833static void _dispc_set_color_mode(enum omap_plane plane, 834 enum omap_color_mode color_mode) 835{ 836 u32 m = 0; 837 838 switch (color_mode) { 839 case OMAP_DSS_COLOR_CLUT1: 840 m = 0x0; break; 841 case OMAP_DSS_COLOR_CLUT2: 842 m = 0x1; break; 843 case OMAP_DSS_COLOR_CLUT4: 844 m = 0x2; break; 845 case OMAP_DSS_COLOR_CLUT8: 846 m = 0x3; break; 847 case OMAP_DSS_COLOR_RGB12U: 848 m = 0x4; break; 849 case OMAP_DSS_COLOR_ARGB16: 850 m = 0x5; break; 851 case OMAP_DSS_COLOR_RGB16: 852 m = 0x6; break; 853 case OMAP_DSS_COLOR_RGB24U: 854 m = 0x8; break; 855 case OMAP_DSS_COLOR_RGB24P: 856 m = 0x9; break; 857 case OMAP_DSS_COLOR_YUV2: 858 m = 0xa; break; 859 case OMAP_DSS_COLOR_UYVY: 860 m = 0xb; break; 861 case OMAP_DSS_COLOR_ARGB32: 862 m = 0xc; break; 863 case OMAP_DSS_COLOR_RGBA32: 864 m = 0xd; break; 865 case OMAP_DSS_COLOR_RGBX32: 866 m = 0xe; break; 867 default: 868 BUG(); break; 869 } 870 871 REG_FLD_MOD(dispc_reg_att[plane], m, 4, 1); 872} 873 874static void _dispc_set_channel_out(enum omap_plane plane, 875 enum omap_channel channel) 876{ 877 int shift; 878 u32 val; 879 880 switch (plane) { 881 case OMAP_DSS_GFX: 882 shift = 8; 883 break; 884 case OMAP_DSS_VIDEO1: 885 case OMAP_DSS_VIDEO2: 886 shift = 16; 887 break; 888 default: 889 BUG(); 890 return; 891 } 892 893 val = dispc_read_reg(dispc_reg_att[plane]); 894 val = FLD_MOD(val, channel, shift, shift); 895 dispc_write_reg(dispc_reg_att[plane], val); 896} 897 898void dispc_set_burst_size(enum omap_plane plane, 899 enum omap_burst_size burst_size) 900{ 901 int shift; 902 u32 val; 903 904 enable_clocks(1); 905 906 switch (plane) { 907 case OMAP_DSS_GFX: 908 shift = 6; 909 break; 910 case OMAP_DSS_VIDEO1: 911 case OMAP_DSS_VIDEO2: 912 shift = 14; 913 break; 914 default: 915 BUG(); 916 return; 917 } 918 919 val = dispc_read_reg(dispc_reg_att[plane]); 920 val = FLD_MOD(val, burst_size, shift+1, shift); 921 dispc_write_reg(dispc_reg_att[plane], val); 922 923 enable_clocks(0); 924} 925 926static void _dispc_set_vid_color_conv(enum omap_plane plane, bool enable) 927{ 928 u32 val; 929 930 BUG_ON(plane == OMAP_DSS_GFX); 931 932 val = dispc_read_reg(dispc_reg_att[plane]); 933 val = FLD_MOD(val, enable, 9, 9); 934 dispc_write_reg(dispc_reg_att[plane], val); 935} 936 937void dispc_enable_replication(enum omap_plane plane, bool enable) 938{ 939 int bit; 940 941 if (plane == OMAP_DSS_GFX) 942 bit = 5; 943 else 944 bit = 10; 945 946 enable_clocks(1); 947 REG_FLD_MOD(dispc_reg_att[plane], enable, bit, bit); 948 enable_clocks(0); 949} 950 951void dispc_set_lcd_size(u16 width, u16 height) 952{ 953 u32 val; 954 BUG_ON((width > (1 << 11)) || (height > (1 << 11))); 955 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 956 enable_clocks(1); 957 dispc_write_reg(DISPC_SIZE_LCD, val); 958 enable_clocks(0); 959} 960 961void dispc_set_digit_size(u16 width, u16 height) 962{ 963 u32 val; 964 BUG_ON((width > (1 << 11)) || (height > (1 << 11))); 965 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); 966 enable_clocks(1); 967 dispc_write_reg(DISPC_SIZE_DIG, val); 968 enable_clocks(0); 969} 970 971static void dispc_read_plane_fifo_sizes(void) 972{ 973 const struct dispc_reg fsz_reg[] = { DISPC_GFX_FIFO_SIZE_STATUS, 974 DISPC_VID_FIFO_SIZE_STATUS(0), 975 DISPC_VID_FIFO_SIZE_STATUS(1) }; 976 u32 size; 977 int plane; 978 979 enable_clocks(1); 980 981 for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) { 982 if (cpu_is_omap24xx()) 983 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0); 984 else if (cpu_is_omap34xx()) 985 size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0); 986 else 987 BUG(); 988 989 dispc.fifo_size[plane] = size; 990 } 991 992 enable_clocks(0); 993} 994 995u32 dispc_get_plane_fifo_size(enum omap_plane plane) 996{ 997 return dispc.fifo_size[plane]; 998} 999 1000void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high) 1001{ 1002 const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD, 1003 DISPC_VID_FIFO_THRESHOLD(0), 1004 DISPC_VID_FIFO_THRESHOLD(1) }; 1005 enable_clocks(1); 1006 1007 DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n", 1008 plane, 1009 REG_GET(ftrs_reg[plane], 11, 0), 1010 REG_GET(ftrs_reg[plane], 27, 16), 1011 low, high); 1012 1013 if (cpu_is_omap24xx()) 1014 dispc_write_reg(ftrs_reg[plane], 1015 FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0)); 1016 else 1017 dispc_write_reg(ftrs_reg[plane], 1018 FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0)); 1019 1020 enable_clocks(0); 1021} 1022 1023void dispc_enable_fifomerge(bool enable) 1024{ 1025 enable_clocks(1); 1026 1027 DSSDBG("FIFO merge %s\n", enable ? "enabled" : "disabled"); 1028 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); 1029 1030 enable_clocks(0); 1031} 1032 1033static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc) 1034{ 1035 u32 val; 1036 const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0), 1037 DISPC_VID_FIR(1) }; 1038 1039 BUG_ON(plane == OMAP_DSS_GFX); 1040 1041 if (cpu_is_omap24xx()) 1042 val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0); 1043 else 1044 val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0); 1045 dispc_write_reg(fir_reg[plane-1], val); 1046} 1047 1048static void _dispc_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) 1049{ 1050 u32 val; 1051 const struct dispc_reg ac0_reg[] = { DISPC_VID_ACCU0(0), 1052 DISPC_VID_ACCU0(1) }; 1053 1054 BUG_ON(plane == OMAP_DSS_GFX); 1055 1056 val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); 1057 dispc_write_reg(ac0_reg[plane-1], val); 1058} 1059 1060static void _dispc_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) 1061{ 1062 u32 val; 1063 const struct dispc_reg ac1_reg[] = { DISPC_VID_ACCU1(0), 1064 DISPC_VID_ACCU1(1) }; 1065 1066 BUG_ON(plane == OMAP_DSS_GFX); 1067 1068 val = FLD_VAL(vaccu, 25, 16) | FLD_VAL(haccu, 9, 0); 1069 dispc_write_reg(ac1_reg[plane-1], val); 1070} 1071 1072 1073static void _dispc_set_scaling(enum omap_plane plane, 1074 u16 orig_width, u16 orig_height, 1075 u16 out_width, u16 out_height, 1076 bool ilace, bool five_taps, 1077 bool fieldmode) 1078{ 1079 int fir_hinc; 1080 int fir_vinc; 1081 int hscaleup, vscaleup; 1082 int accu0 = 0; 1083 int accu1 = 0; 1084 u32 l; 1085 1086 BUG_ON(plane == OMAP_DSS_GFX); 1087 1088 hscaleup = orig_width <= out_width; 1089 vscaleup = orig_height <= out_height; 1090 1091 _dispc_set_scale_coef(plane, hscaleup, vscaleup, five_taps); 1092 1093 if (!orig_width || orig_width == out_width) 1094 fir_hinc = 0; 1095 else 1096 fir_hinc = 1024 * orig_width / out_width; 1097 1098 if (!orig_height || orig_height == out_height) 1099 fir_vinc = 0; 1100 else 1101 fir_vinc = 1024 * orig_height / out_height; 1102 1103 _dispc_set_fir(plane, fir_hinc, fir_vinc); 1104 1105 l = dispc_read_reg(dispc_reg_att[plane]); 1106 l &= ~((0x0f << 5) | (0x3 << 21)); 1107 1108 l |= fir_hinc ? (1 << 5) : 0; 1109 l |= fir_vinc ? (1 << 6) : 0; 1110 1111 l |= hscaleup ? 0 : (1 << 7); 1112 l |= vscaleup ? 0 : (1 << 8); 1113 1114 l |= five_taps ? (1 << 21) : 0; 1115 l |= five_taps ? (1 << 22) : 0; 1116 1117 dispc_write_reg(dispc_reg_att[plane], l); 1118 1119 /* 1120 * field 0 = even field = bottom field 1121 * field 1 = odd field = top field 1122 */ 1123 if (ilace && !fieldmode) { 1124 accu1 = 0; 1125 accu0 = (fir_vinc / 2) & 0x3ff; 1126 if (accu0 >= 1024/2) { 1127 accu1 = 1024/2; 1128 accu0 -= accu1; 1129 } 1130 } 1131 1132 _dispc_set_vid_accu0(plane, 0, accu0); 1133 _dispc_set_vid_accu1(plane, 0, accu1); 1134} 1135 1136static void _dispc_set_rotation_attrs(enum omap_plane plane, u8 rotation, 1137 bool mirroring, enum omap_color_mode color_mode) 1138{ 1139 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1140 color_mode == OMAP_DSS_COLOR_UYVY) { 1141 int vidrot = 0; 1142 1143 if (mirroring) { 1144 switch (rotation) { 1145 case OMAP_DSS_ROT_0: 1146 vidrot = 2; 1147 break; 1148 case OMAP_DSS_ROT_90: 1149 vidrot = 1; 1150 break; 1151 case OMAP_DSS_ROT_180: 1152 vidrot = 0; 1153 break; 1154 case OMAP_DSS_ROT_270: 1155 vidrot = 3; 1156 break; 1157 } 1158 } else { 1159 switch (rotation) { 1160 case OMAP_DSS_ROT_0: 1161 vidrot = 0; 1162 break; 1163 case OMAP_DSS_ROT_90: 1164 vidrot = 1; 1165 break; 1166 case OMAP_DSS_ROT_180: 1167 vidrot = 2; 1168 break; 1169 case OMAP_DSS_ROT_270: 1170 vidrot = 3; 1171 break; 1172 } 1173 } 1174 1175 REG_FLD_MOD(dispc_reg_att[plane], vidrot, 13, 12); 1176 1177 if (rotation == OMAP_DSS_ROT_90 || rotation == OMAP_DSS_ROT_270) 1178 REG_FLD_MOD(dispc_reg_att[plane], 0x1, 18, 18); 1179 else 1180 REG_FLD_MOD(dispc_reg_att[plane], 0x0, 18, 18); 1181 } else { 1182 REG_FLD_MOD(dispc_reg_att[plane], 0, 13, 12); 1183 REG_FLD_MOD(dispc_reg_att[plane], 0, 18, 18); 1184 } 1185} 1186 1187static int color_mode_to_bpp(enum omap_color_mode color_mode) 1188{ 1189 switch (color_mode) { 1190 case OMAP_DSS_COLOR_CLUT1: 1191 return 1; 1192 case OMAP_DSS_COLOR_CLUT2: 1193 return 2; 1194 case OMAP_DSS_COLOR_CLUT4: 1195 return 4; 1196 case OMAP_DSS_COLOR_CLUT8: 1197 return 8; 1198 case OMAP_DSS_COLOR_RGB12U: 1199 case OMAP_DSS_COLOR_RGB16: 1200 case OMAP_DSS_COLOR_ARGB16: 1201 case OMAP_DSS_COLOR_YUV2: 1202 case OMAP_DSS_COLOR_UYVY: 1203 return 16; 1204 case OMAP_DSS_COLOR_RGB24P: 1205 return 24; 1206 case OMAP_DSS_COLOR_RGB24U: 1207 case OMAP_DSS_COLOR_ARGB32: 1208 case OMAP_DSS_COLOR_RGBA32: 1209 case OMAP_DSS_COLOR_RGBX32: 1210 return 32; 1211 default: 1212 BUG(); 1213 } 1214} 1215 1216static s32 pixinc(int pixels, u8 ps) 1217{ 1218 if (pixels == 1) 1219 return 1; 1220 else if (pixels > 1) 1221 return 1 + (pixels - 1) * ps; 1222 else if (pixels < 0) 1223 return 1 - (-pixels + 1) * ps; 1224 else 1225 BUG(); 1226} 1227 1228static void calc_vrfb_rotation_offset(u8 rotation, bool mirror, 1229 u16 screen_width, 1230 u16 width, u16 height, 1231 enum omap_color_mode color_mode, bool fieldmode, 1232 unsigned int field_offset, 1233 unsigned *offset0, unsigned *offset1, 1234 s32 *row_inc, s32 *pix_inc) 1235{ 1236 u8 ps; 1237 1238 switch (color_mode) { 1239 case OMAP_DSS_COLOR_CLUT1: 1240 case OMAP_DSS_COLOR_CLUT2: 1241 case OMAP_DSS_COLOR_CLUT4: 1242 case OMAP_DSS_COLOR_CLUT8: 1243 BUG(); 1244 return; 1245 case OMAP_DSS_COLOR_YUV2: 1246 case OMAP_DSS_COLOR_UYVY: 1247 ps = 4; 1248 break; 1249 default: 1250 ps = color_mode_to_bpp(color_mode) / 8; 1251 break; 1252 } 1253 1254 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, 1255 width, height); 1256 1257 /* 1258 * field 0 = even field = bottom field 1259 * field 1 = odd field = top field 1260 */ 1261 switch (rotation + mirror * 4) { 1262 case OMAP_DSS_ROT_0: 1263 case OMAP_DSS_ROT_180: 1264 /* 1265 * If the pixel format is YUV or UYVY divide the width 1266 * of the image by 2 for 0 and 180 degree rotation. 1267 */ 1268 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1269 color_mode == OMAP_DSS_COLOR_UYVY) 1270 width = width >> 1; 1271 case OMAP_DSS_ROT_90: 1272 case OMAP_DSS_ROT_270: 1273 *offset1 = 0; 1274 if (field_offset) 1275 *offset0 = field_offset * screen_width * ps; 1276 else 1277 *offset0 = 0; 1278 1279 *row_inc = pixinc(1 + (screen_width - width) + 1280 (fieldmode ? screen_width : 0), 1281 ps); 1282 *pix_inc = pixinc(1, ps); 1283 break; 1284 1285 case OMAP_DSS_ROT_0 + 4: 1286 case OMAP_DSS_ROT_180 + 4: 1287 /* If the pixel format is YUV or UYVY divide the width 1288 * of the image by 2 for 0 degree and 180 degree 1289 */ 1290 if (color_mode == OMAP_DSS_COLOR_YUV2 || 1291 color_mode == OMAP_DSS_COLOR_UYVY) 1292 width = width >> 1; 1293 case OMAP_DSS_ROT_90 + 4: 1294 case OMAP_DSS_ROT_270 + 4: 1295 *offset1 = 0; 1296 if (field_offset) 1297 *offset0 = field_offset * screen_width * ps; 1298 else 1299 *offset0 = 0; 1300 *row_inc = pixinc(1 - (screen_width + width) - 1301 (fieldmode ? screen_width : 0), 1302 ps); 1303 *pix_inc = pixinc(1, ps); 1304 break; 1305 1306 default: 1307 BUG(); 1308 } 1309} 1310 1311static void calc_dma_rotation_offset(u8 rotation, bool mirror, 1312 u16 screen_width, 1313 u16 width, u16 height, 1314 enum omap_color_mode color_mode, bool fieldmode, 1315 unsigned int field_offset, 1316 unsigned *offset0, unsigned *offset1, 1317 s32 *row_inc, s32 *pix_inc) 1318{ 1319 u8 ps; 1320 u16 fbw, fbh; 1321 1322 switch (color_mode) { 1323 case OMAP_DSS_COLOR_CLUT1: 1324 case OMAP_DSS_COLOR_CLUT2: 1325 case OMAP_DSS_COLOR_CLUT4: 1326 case OMAP_DSS_COLOR_CLUT8: 1327 BUG(); 1328 return; 1329 default: 1330 ps = color_mode_to_bpp(color_mode) / 8; 1331 break; 1332 } 1333 1334 DSSDBG("calc_rot(%d): scrw %d, %dx%d\n", rotation, screen_width, 1335 width, height); 1336 1337 /* width & height are overlay sizes, convert to fb sizes */ 1338 1339 if (rotation == OMAP_DSS_ROT_0 || rotation == OMAP_DSS_ROT_180) { 1340 fbw = width; 1341 fbh = height; 1342 } else { 1343 fbw = height; 1344 fbh = width; 1345 } 1346 1347 /* 1348 * field 0 = even field = bottom field 1349 * field 1 = odd field = top field 1350 */ 1351 switch (rotation + mirror * 4) { 1352 case OMAP_DSS_ROT_0: 1353 *offset1 = 0; 1354 if (field_offset) 1355 *offset0 = *offset1 + field_offset * screen_width * ps; 1356 else 1357 *offset0 = *offset1; 1358 *row_inc = pixinc(1 + (screen_width - fbw) + 1359 (fieldmode ? screen_width : 0), 1360 ps); 1361 *pix_inc = pixinc(1, ps); 1362 break; 1363 case OMAP_DSS_ROT_90: 1364 *offset1 = screen_width * (fbh - 1) * ps; 1365 if (field_offset) 1366 *offset0 = *offset1 + field_offset * ps; 1367 else 1368 *offset0 = *offset1; 1369 *row_inc = pixinc(screen_width * (fbh - 1) + 1 + 1370 (fieldmode ? 1 : 0), ps); 1371 *pix_inc = pixinc(-screen_width, ps); 1372 break; 1373 case OMAP_DSS_ROT_180: 1374 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; 1375 if (field_offset) 1376 *offset0 = *offset1 - field_offset * screen_width * ps; 1377 else 1378 *offset0 = *offset1; 1379 *row_inc = pixinc(-1 - 1380 (screen_width - fbw) - 1381 (fieldmode ? screen_width : 0), 1382 ps); 1383 *pix_inc = pixinc(-1, ps); 1384 break; 1385 case OMAP_DSS_ROT_270: 1386 *offset1 = (fbw - 1) * ps; 1387 if (field_offset) 1388 *offset0 = *offset1 - field_offset * ps; 1389 else 1390 *offset0 = *offset1; 1391 *row_inc = pixinc(-screen_width * (fbh - 1) - 1 - 1392 (fieldmode ? 1 : 0), ps); 1393 *pix_inc = pixinc(screen_width, ps); 1394 break; 1395 1396 /* mirroring */ 1397 case OMAP_DSS_ROT_0 + 4: 1398 *offset1 = (fbw - 1) * ps; 1399 if (field_offset) 1400 *offset0 = *offset1 + field_offset * screen_width * ps; 1401 else 1402 *offset0 = *offset1; 1403 *row_inc = pixinc(screen_width * 2 - 1 + 1404 (fieldmode ? screen_width : 0), 1405 ps); 1406 *pix_inc = pixinc(-1, ps); 1407 break; 1408 1409 case OMAP_DSS_ROT_90 + 4: 1410 *offset1 = 0; 1411 if (field_offset) 1412 *offset0 = *offset1 + field_offset * ps; 1413 else 1414 *offset0 = *offset1; 1415 *row_inc = pixinc(-screen_width * (fbh - 1) + 1 + 1416 (fieldmode ? 1 : 0), 1417 ps); 1418 *pix_inc = pixinc(screen_width, ps); 1419 break; 1420 1421 case OMAP_DSS_ROT_180 + 4: 1422 *offset1 = screen_width * (fbh - 1) * ps; 1423 if (field_offset) 1424 *offset0 = *offset1 - field_offset * screen_width * ps; 1425 else 1426 *offset0 = *offset1; 1427 *row_inc = pixinc(1 - screen_width * 2 - 1428 (fieldmode ? screen_width : 0), 1429 ps); 1430 *pix_inc = pixinc(1, ps); 1431 break; 1432 1433 case OMAP_DSS_ROT_270 + 4: 1434 *offset1 = (screen_width * (fbh - 1) + fbw - 1) * ps; 1435 if (field_offset) 1436 *offset0 = *offset1 - field_offset * ps; 1437 else 1438 *offset0 = *offset1; 1439 *row_inc = pixinc(screen_width * (fbh - 1) - 1 - 1440 (fieldmode ? 1 : 0), 1441 ps); 1442 *pix_inc = pixinc(-screen_width, ps); 1443 break; 1444 1445 default: 1446 BUG(); 1447 } 1448} 1449 1450static unsigned long calc_fclk_five_taps(u16 width, u16 height, 1451 u16 out_width, u16 out_height, enum omap_color_mode color_mode) 1452{ 1453 u32 fclk = 0; 1454 u64 tmp, pclk = dispc_pclk_rate(); 1455 1456 if (height > out_height) { 1457 unsigned int ppl = 800; 1458 1459 tmp = pclk * height * out_width; 1460 do_div(tmp, 2 * out_height * ppl); 1461 fclk = tmp; 1462 1463 if (height > 2 * out_height) { 1464 if (ppl == out_width) 1465 return 0; 1466 1467 tmp = pclk * (height - 2 * out_height) * out_width; 1468 do_div(tmp, 2 * out_height * (ppl - out_width)); 1469 fclk = max(fclk, (u32) tmp); 1470 } 1471 } 1472 1473 if (width > out_width) { 1474 tmp = pclk * width; 1475 do_div(tmp, out_width); 1476 fclk = max(fclk, (u32) tmp); 1477 1478 if (color_mode == OMAP_DSS_COLOR_RGB24U) 1479 fclk <<= 1; 1480 } 1481 1482 return fclk; 1483} 1484 1485static unsigned long calc_fclk(u16 width, u16 height, 1486 u16 out_width, u16 out_height) 1487{ 1488 unsigned int hf, vf; 1489 1490 1491 if (width > 3 * out_width) 1492 hf = 4; 1493 else if (width > 2 * out_width) 1494 hf = 3; 1495 else if (width > out_width) 1496 hf = 2; 1497 else 1498 hf = 1; 1499 1500 if (height > out_height) 1501 vf = 2; 1502 else 1503 vf = 1; 1504 1505 return dispc_pclk_rate() * vf * hf; 1506} 1507 1508void dispc_set_channel_out(enum omap_plane plane, enum omap_channel channel_out) 1509{ 1510 enable_clocks(1); 1511 _dispc_set_channel_out(plane, channel_out); 1512 enable_clocks(0); 1513} 1514 1515static int _dispc_setup_plane(enum omap_plane plane, 1516 u32 paddr, u16 screen_width, 1517 u16 pos_x, u16 pos_y, 1518 u16 width, u16 height, 1519 u16 out_width, u16 out_height, 1520 enum omap_color_mode color_mode, 1521 bool ilace, 1522 enum omap_dss_rotation_type rotation_type, 1523 u8 rotation, int mirror, 1524 u8 global_alpha) 1525{ 1526 const int maxdownscale = cpu_is_omap34xx() ? 4 : 2; 1527 bool five_taps = 0; 1528 bool fieldmode = 0; 1529 int cconv = 0; 1530 unsigned offset0, offset1; 1531 s32 row_inc; 1532 s32 pix_inc; 1533 u16 frame_height = height; 1534 unsigned int field_offset = 0; 1535 1536 if (paddr == 0) 1537 return -EINVAL; 1538 1539 if (ilace && height == out_height) 1540 fieldmode = 1; 1541 1542 if (ilace) { 1543 if (fieldmode) 1544 height /= 2; 1545 pos_y /= 2; 1546 out_height /= 2; 1547 1548 DSSDBG("adjusting for ilace: height %d, pos_y %d, " 1549 "out_height %d\n", 1550 height, pos_y, out_height); 1551 } 1552 1553 if (plane == OMAP_DSS_GFX) { 1554 if (width != out_width || height != out_height) 1555 return -EINVAL; 1556 1557 switch (color_mode) { 1558 case OMAP_DSS_COLOR_ARGB16: 1559 case OMAP_DSS_COLOR_ARGB32: 1560 case OMAP_DSS_COLOR_RGBA32: 1561 case OMAP_DSS_COLOR_RGBX32: 1562 if (cpu_is_omap24xx()) 1563 return -EINVAL; 1564 /* fall through */ 1565 case OMAP_DSS_COLOR_RGB12U: 1566 case OMAP_DSS_COLOR_RGB16: 1567 case OMAP_DSS_COLOR_RGB24P: 1568 case OMAP_DSS_COLOR_RGB24U: 1569 break; 1570 1571 default: 1572 return -EINVAL; 1573 } 1574 } else { 1575 /* video plane */ 1576 1577 unsigned long fclk = 0; 1578 1579 if (out_width < width / maxdownscale || 1580 out_width > width * 8) 1581 return -EINVAL; 1582 1583 if (out_height < height / maxdownscale || 1584 out_height > height * 8) 1585 return -EINVAL; 1586 1587 switch (color_mode) { 1588 case OMAP_DSS_COLOR_RGBX32: 1589 case OMAP_DSS_COLOR_RGB12U: 1590 if (cpu_is_omap24xx()) 1591 return -EINVAL; 1592 /* fall through */ 1593 case OMAP_DSS_COLOR_RGB16: 1594 case OMAP_DSS_COLOR_RGB24P: 1595 case OMAP_DSS_COLOR_RGB24U: 1596 break; 1597 1598 case OMAP_DSS_COLOR_ARGB16: 1599 case OMAP_DSS_COLOR_ARGB32: 1600 case OMAP_DSS_COLOR_RGBA32: 1601 if (cpu_is_omap24xx()) 1602 return -EINVAL; 1603 if (plane == OMAP_DSS_VIDEO1) 1604 return -EINVAL; 1605 break; 1606 1607 case OMAP_DSS_COLOR_YUV2: 1608 case OMAP_DSS_COLOR_UYVY: 1609 cconv = 1; 1610 break; 1611 1612 default: 1613 return -EINVAL; 1614 } 1615 1616 /* Must use 5-tap filter? */ 1617 five_taps = height > out_height * 2; 1618 1619 if (!five_taps) { 1620 fclk = calc_fclk(width, height, 1621 out_width, out_height); 1622 1623 /* Try 5-tap filter if 3-tap fclk is too high */ 1624 if (cpu_is_omap34xx() && height > out_height && 1625 fclk > dispc_fclk_rate()) 1626 five_taps = true; 1627 } 1628 1629 if (width > (2048 >> five_taps)) { 1630 DSSERR("failed to set up scaling, fclk too low\n"); 1631 return -EINVAL; 1632 } 1633 1634 if (five_taps) 1635 fclk = calc_fclk_five_taps(width, height, 1636 out_width, out_height, color_mode); 1637 1638 DSSDBG("required fclk rate = %lu Hz\n", fclk); 1639 DSSDBG("current fclk rate = %lu Hz\n", dispc_fclk_rate()); 1640 1641 if (!fclk || fclk > dispc_fclk_rate()) { 1642 DSSERR("failed to set up scaling, " 1643 "required fclk rate = %lu Hz, " 1644 "current fclk rate = %lu Hz\n", 1645 fclk, dispc_fclk_rate()); 1646 return -EINVAL; 1647 } 1648 } 1649 1650 if (ilace && !fieldmode) { 1651 /* 1652 * when downscaling the bottom field may have to start several 1653 * source lines below the top field. Unfortunately ACCUI 1654 * registers will only hold the fractional part of the offset 1655 * so the integer part must be added to the base address of the 1656 * bottom field. 1657 */ 1658 if (!height || height == out_height) 1659 field_offset = 0; 1660 else 1661 field_offset = height / out_height / 2; 1662 } 1663 1664 /* Fields are independent but interleaved in memory. */ 1665 if (fieldmode) 1666 field_offset = 1; 1667 1668 if (rotation_type == OMAP_DSS_ROT_DMA) 1669 calc_dma_rotation_offset(rotation, mirror, 1670 screen_width, width, frame_height, color_mode, 1671 fieldmode, field_offset, 1672 &offset0, &offset1, &row_inc, &pix_inc); 1673 else 1674 calc_vrfb_rotation_offset(rotation, mirror, 1675 screen_width, width, frame_height, color_mode, 1676 fieldmode, field_offset, 1677 &offset0, &offset1, &row_inc, &pix_inc); 1678 1679 DSSDBG("offset0 %u, offset1 %u, row_inc %d, pix_inc %d\n", 1680 offset0, offset1, row_inc, pix_inc); 1681 1682 _dispc_set_color_mode(plane, color_mode); 1683 1684 _dispc_set_plane_ba0(plane, paddr + offset0); 1685 _dispc_set_plane_ba1(plane, paddr + offset1); 1686 1687 _dispc_set_row_inc(plane, row_inc); 1688 _dispc_set_pix_inc(plane, pix_inc); 1689 1690 DSSDBG("%d,%d %dx%d -> %dx%d\n", pos_x, pos_y, width, height, 1691 out_width, out_height); 1692 1693 _dispc_set_plane_pos(plane, pos_x, pos_y); 1694 1695 _dispc_set_pic_size(plane, width, height); 1696 1697 if (plane != OMAP_DSS_GFX) { 1698 _dispc_set_scaling(plane, width, height, 1699 out_width, out_height, 1700 ilace, five_taps, fieldmode); 1701 _dispc_set_vid_size(plane, out_width, out_height); 1702 _dispc_set_vid_color_conv(plane, cconv); 1703 } 1704 1705 _dispc_set_rotation_attrs(plane, rotation, mirror, color_mode); 1706 1707 if (plane != OMAP_DSS_VIDEO1) 1708 _dispc_setup_global_alpha(plane, global_alpha); 1709 1710 return 0; 1711} 1712 1713static void _dispc_enable_plane(enum omap_plane plane, bool enable) 1714{ 1715 REG_FLD_MOD(dispc_reg_att[plane], enable ? 1 : 0, 0, 0); 1716} 1717 1718static void dispc_disable_isr(void *data, u32 mask) 1719{ 1720 struct completion *compl = data; 1721 complete(compl); 1722} 1723 1724static void _enable_lcd_out(bool enable) 1725{ 1726 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0); 1727} 1728 1729static void dispc_enable_lcd_out(bool enable) 1730{ 1731 struct completion frame_done_completion; 1732 bool is_on; 1733 int r; 1734 1735 enable_clocks(1); 1736 1737 /* When we disable LCD output, we need to wait until frame is done. 1738 * Otherwise the DSS is still working, and turning off the clocks 1739 * prevents DSS from going to OFF mode */ 1740 is_on = REG_GET(DISPC_CONTROL, 0, 0); 1741 1742 if (!enable && is_on) { 1743 init_completion(&frame_done_completion); 1744 1745 r = omap_dispc_register_isr(dispc_disable_isr, 1746 &frame_done_completion, 1747 DISPC_IRQ_FRAMEDONE); 1748 1749 if (r) 1750 DSSERR("failed to register FRAMEDONE isr\n"); 1751 } 1752 1753 _enable_lcd_out(enable); 1754 1755 if (!enable && is_on) { 1756 if (!wait_for_completion_timeout(&frame_done_completion, 1757 msecs_to_jiffies(100))) 1758 DSSERR("timeout waiting for FRAME DONE\n"); 1759 1760 r = omap_dispc_unregister_isr(dispc_disable_isr, 1761 &frame_done_completion, 1762 DISPC_IRQ_FRAMEDONE); 1763 1764 if (r) 1765 DSSERR("failed to unregister FRAMEDONE isr\n"); 1766 } 1767 1768 enable_clocks(0); 1769} 1770 1771static void _enable_digit_out(bool enable) 1772{ 1773 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1); 1774} 1775 1776static void dispc_enable_digit_out(bool enable) 1777{ 1778 struct completion frame_done_completion; 1779 int r; 1780 1781 enable_clocks(1); 1782 1783 if (REG_GET(DISPC_CONTROL, 1, 1) == enable) { 1784 enable_clocks(0); 1785 return; 1786 } 1787 1788 if (enable) { 1789 unsigned long flags; 1790 /* When we enable digit output, we'll get an extra digit 1791 * sync lost interrupt, that we need to ignore */ 1792 spin_lock_irqsave(&dispc.irq_lock, flags); 1793 dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; 1794 _omap_dispc_set_irqs(); 1795 spin_unlock_irqrestore(&dispc.irq_lock, flags); 1796 } 1797 1798 /* When we disable digit output, we need to wait until fields are done. 1799 * Otherwise the DSS is still working, and turning off the clocks 1800 * prevents DSS from going to OFF mode. And when enabling, we need to 1801 * wait for the extra sync losts */ 1802 init_completion(&frame_done_completion); 1803 1804 r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, 1805 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); 1806 if (r) 1807 DSSERR("failed to register EVSYNC isr\n"); 1808 1809 _enable_digit_out(enable); 1810 1811 if (!wait_for_completion_timeout(&frame_done_completion, 1812 msecs_to_jiffies(100))) 1813 DSSERR("timeout waiting for EVSYNC\n"); 1814 1815 if (!wait_for_completion_timeout(&frame_done_completion, 1816 msecs_to_jiffies(100))) 1817 DSSERR("timeout waiting for EVSYNC\n"); 1818 1819 r = omap_dispc_unregister_isr(dispc_disable_isr, 1820 &frame_done_completion, 1821 DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD); 1822 if (r) 1823 DSSERR("failed to unregister EVSYNC isr\n"); 1824 1825 if (enable) { 1826 unsigned long flags; 1827 spin_lock_irqsave(&dispc.irq_lock, flags); 1828 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; 1829 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); 1830 _omap_dispc_set_irqs(); 1831 spin_unlock_irqrestore(&dispc.irq_lock, flags); 1832 } 1833 1834 enable_clocks(0); 1835} 1836 1837bool dispc_is_channel_enabled(enum omap_channel channel) 1838{ 1839 if (channel == OMAP_DSS_CHANNEL_LCD) 1840 return !!REG_GET(DISPC_CONTROL, 0, 0); 1841 else if (channel == OMAP_DSS_CHANNEL_DIGIT) 1842 return !!REG_GET(DISPC_CONTROL, 1, 1); 1843 else 1844 BUG(); 1845} 1846 1847void dispc_enable_channel(enum omap_channel channel, bool enable) 1848{ 1849 if (channel == OMAP_DSS_CHANNEL_LCD) 1850 dispc_enable_lcd_out(enable); 1851 else if (channel == OMAP_DSS_CHANNEL_DIGIT) 1852 dispc_enable_digit_out(enable); 1853 else 1854 BUG(); 1855} 1856 1857void dispc_lcd_enable_signal_polarity(bool act_high) 1858{ 1859 enable_clocks(1); 1860 REG_FLD_MOD(DISPC_CONTROL, act_high ? 1 : 0, 29, 29); 1861 enable_clocks(0); 1862} 1863 1864void dispc_lcd_enable_signal(bool enable) 1865{ 1866 enable_clocks(1); 1867 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 28, 28); 1868 enable_clocks(0); 1869} 1870 1871void dispc_pck_free_enable(bool enable) 1872{ 1873 enable_clocks(1); 1874 REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); 1875 enable_clocks(0); 1876} 1877 1878void dispc_enable_fifohandcheck(bool enable) 1879{ 1880 enable_clocks(1); 1881 REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 16, 16); 1882 enable_clocks(0); 1883} 1884 1885 1886void dispc_set_lcd_display_type(enum omap_lcd_display_type type) 1887{ 1888 int mode; 1889 1890 switch (type) { 1891 case OMAP_DSS_LCD_DISPLAY_STN: 1892 mode = 0; 1893 break; 1894 1895 case OMAP_DSS_LCD_DISPLAY_TFT: 1896 mode = 1; 1897 break; 1898 1899 default: 1900 BUG(); 1901 return; 1902 } 1903 1904 enable_clocks(1); 1905 REG_FLD_MOD(DISPC_CONTROL, mode, 3, 3); 1906 enable_clocks(0); 1907} 1908 1909void dispc_set_loadmode(enum omap_dss_load_mode mode) 1910{ 1911 enable_clocks(1); 1912 REG_FLD_MOD(DISPC_CONFIG, mode, 2, 1); 1913 enable_clocks(0); 1914} 1915 1916 1917void dispc_set_default_color(enum omap_channel channel, u32 color) 1918{ 1919 const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, 1920 DISPC_DEFAULT_COLOR1 }; 1921 1922 enable_clocks(1); 1923 dispc_write_reg(def_reg[channel], color); 1924 enable_clocks(0); 1925} 1926 1927u32 dispc_get_default_color(enum omap_channel channel) 1928{ 1929 const struct dispc_reg def_reg[] = { DISPC_DEFAULT_COLOR0, 1930 DISPC_DEFAULT_COLOR1 }; 1931 u32 l; 1932 1933 BUG_ON(channel != OMAP_DSS_CHANNEL_DIGIT && 1934 channel != OMAP_DSS_CHANNEL_LCD); 1935 1936 enable_clocks(1); 1937 l = dispc_read_reg(def_reg[channel]); 1938 enable_clocks(0); 1939 1940 return l; 1941} 1942 1943void dispc_set_trans_key(enum omap_channel ch, 1944 enum omap_dss_trans_key_type type, 1945 u32 trans_key) 1946{ 1947 const struct dispc_reg tr_reg[] = { 1948 DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; 1949 1950 enable_clocks(1); 1951 if (ch == OMAP_DSS_CHANNEL_LCD) 1952 REG_FLD_MOD(DISPC_CONFIG, type, 11, 11); 1953 else /* OMAP_DSS_CHANNEL_DIGIT */ 1954 REG_FLD_MOD(DISPC_CONFIG, type, 13, 13); 1955 1956 dispc_write_reg(tr_reg[ch], trans_key); 1957 enable_clocks(0); 1958} 1959 1960void dispc_get_trans_key(enum omap_channel ch, 1961 enum omap_dss_trans_key_type *type, 1962 u32 *trans_key) 1963{ 1964 const struct dispc_reg tr_reg[] = { 1965 DISPC_TRANS_COLOR0, DISPC_TRANS_COLOR1 }; 1966 1967 enable_clocks(1); 1968 if (type) { 1969 if (ch == OMAP_DSS_CHANNEL_LCD) 1970 *type = REG_GET(DISPC_CONFIG, 11, 11); 1971 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 1972 *type = REG_GET(DISPC_CONFIG, 13, 13); 1973 else 1974 BUG(); 1975 } 1976 1977 if (trans_key) 1978 *trans_key = dispc_read_reg(tr_reg[ch]); 1979 enable_clocks(0); 1980} 1981 1982void dispc_enable_trans_key(enum omap_channel ch, bool enable) 1983{ 1984 enable_clocks(1); 1985 if (ch == OMAP_DSS_CHANNEL_LCD) 1986 REG_FLD_MOD(DISPC_CONFIG, enable, 10, 10); 1987 else /* OMAP_DSS_CHANNEL_DIGIT */ 1988 REG_FLD_MOD(DISPC_CONFIG, enable, 12, 12); 1989 enable_clocks(0); 1990} 1991void dispc_enable_alpha_blending(enum omap_channel ch, bool enable) 1992{ 1993 if (cpu_is_omap24xx()) 1994 return; 1995 1996 enable_clocks(1); 1997 if (ch == OMAP_DSS_CHANNEL_LCD) 1998 REG_FLD_MOD(DISPC_CONFIG, enable, 18, 18); 1999 else /* OMAP_DSS_CHANNEL_DIGIT */ 2000 REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); 2001 enable_clocks(0); 2002} 2003bool dispc_alpha_blending_enabled(enum omap_channel ch) 2004{ 2005 bool enabled; 2006 2007 if (cpu_is_omap24xx()) 2008 return false; 2009 2010 enable_clocks(1); 2011 if (ch == OMAP_DSS_CHANNEL_LCD) 2012 enabled = REG_GET(DISPC_CONFIG, 18, 18); 2013 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2014 enabled = REG_GET(DISPC_CONFIG, 18, 18); 2015 else 2016 BUG(); 2017 enable_clocks(0); 2018 2019 return enabled; 2020 2021} 2022 2023 2024bool dispc_trans_key_enabled(enum omap_channel ch) 2025{ 2026 bool enabled; 2027 2028 enable_clocks(1); 2029 if (ch == OMAP_DSS_CHANNEL_LCD) 2030 enabled = REG_GET(DISPC_CONFIG, 10, 10); 2031 else if (ch == OMAP_DSS_CHANNEL_DIGIT) 2032 enabled = REG_GET(DISPC_CONFIG, 12, 12); 2033 else 2034 BUG(); 2035 enable_clocks(0); 2036 2037 return enabled; 2038} 2039 2040 2041void dispc_set_tft_data_lines(u8 data_lines) 2042{ 2043 int code; 2044 2045 switch (data_lines) { 2046 case 12: 2047 code = 0; 2048 break; 2049 case 16: 2050 code = 1; 2051 break; 2052 case 18: 2053 code = 2; 2054 break; 2055 case 24: 2056 code = 3; 2057 break; 2058 default: 2059 BUG(); 2060 return; 2061 } 2062 2063 enable_clocks(1); 2064 REG_FLD_MOD(DISPC_CONTROL, code, 9, 8); 2065 enable_clocks(0); 2066} 2067 2068void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode) 2069{ 2070 u32 l; 2071 int stallmode; 2072 int gpout0 = 1; 2073 int gpout1; 2074 2075 switch (mode) { 2076 case OMAP_DSS_PARALLELMODE_BYPASS: 2077 stallmode = 0; 2078 gpout1 = 1; 2079 break; 2080 2081 case OMAP_DSS_PARALLELMODE_RFBI: 2082 stallmode = 1; 2083 gpout1 = 0; 2084 break; 2085 2086 case OMAP_DSS_PARALLELMODE_DSI: 2087 stallmode = 1; 2088 gpout1 = 1; 2089 break; 2090 2091 default: 2092 BUG(); 2093 return; 2094 } 2095 2096 enable_clocks(1); 2097 2098 l = dispc_read_reg(DISPC_CONTROL); 2099 2100 l = FLD_MOD(l, stallmode, 11, 11); 2101 l = FLD_MOD(l, gpout0, 15, 15); 2102 l = FLD_MOD(l, gpout1, 16, 16); 2103 2104 dispc_write_reg(DISPC_CONTROL, l); 2105 2106 enable_clocks(0); 2107} 2108 2109static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, 2110 int vsw, int vfp, int vbp) 2111{ 2112 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2113 if (hsw < 1 || hsw > 64 || 2114 hfp < 1 || hfp > 256 || 2115 hbp < 1 || hbp > 256 || 2116 vsw < 1 || vsw > 64 || 2117 vfp < 0 || vfp > 255 || 2118 vbp < 0 || vbp > 255) 2119 return false; 2120 } else { 2121 if (hsw < 1 || hsw > 256 || 2122 hfp < 1 || hfp > 4096 || 2123 hbp < 1 || hbp > 4096 || 2124 vsw < 1 || vsw > 256 || 2125 vfp < 0 || vfp > 4095 || 2126 vbp < 0 || vbp > 4095) 2127 return false; 2128 } 2129 2130 return true; 2131} 2132 2133bool dispc_lcd_timings_ok(struct omap_video_timings *timings) 2134{ 2135 return _dispc_lcd_timings_ok(timings->hsw, timings->hfp, 2136 timings->hbp, timings->vsw, 2137 timings->vfp, timings->vbp); 2138} 2139 2140static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp, 2141 int vsw, int vfp, int vbp) 2142{ 2143 u32 timing_h, timing_v; 2144 2145 if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) { 2146 timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) | 2147 FLD_VAL(hbp-1, 27, 20); 2148 2149 timing_v = FLD_VAL(vsw-1, 5, 0) | FLD_VAL(vfp, 15, 8) | 2150 FLD_VAL(vbp, 27, 20); 2151 } else { 2152 timing_h = FLD_VAL(hsw-1, 7, 0) | FLD_VAL(hfp-1, 19, 8) | 2153 FLD_VAL(hbp-1, 31, 20); 2154 2155 timing_v = FLD_VAL(vsw-1, 7, 0) | FLD_VAL(vfp, 19, 8) | 2156 FLD_VAL(vbp, 31, 20); 2157 } 2158 2159 enable_clocks(1); 2160 dispc_write_reg(DISPC_TIMING_H, timing_h); 2161 dispc_write_reg(DISPC_TIMING_V, timing_v); 2162 enable_clocks(0); 2163} 2164 2165/* change name to mode? */ 2166void dispc_set_lcd_timings(struct omap_video_timings *timings) 2167{ 2168 unsigned xtot, ytot; 2169 unsigned long ht, vt; 2170 2171 if (!_dispc_lcd_timings_ok(timings->hsw, timings->hfp, 2172 timings->hbp, timings->vsw, 2173 timings->vfp, timings->vbp)) 2174 BUG(); 2175 2176 _dispc_set_lcd_timings(timings->hsw, timings->hfp, timings->hbp, 2177 timings->vsw, timings->vfp, timings->vbp); 2178 2179 dispc_set_lcd_size(timings->x_res, timings->y_res); 2180 2181 xtot = timings->x_res + timings->hfp + timings->hsw + timings->hbp; 2182 ytot = timings->y_res + timings->vfp + timings->vsw + timings->vbp; 2183 2184 ht = (timings->pixel_clock * 1000) / xtot; 2185 vt = (timings->pixel_clock * 1000) / xtot / ytot; 2186 2187 DSSDBG("xres %u yres %u\n", timings->x_res, timings->y_res); 2188 DSSDBG("pck %u\n", timings->pixel_clock); 2189 DSSDBG("hsw %d hfp %d hbp %d vsw %d vfp %d vbp %d\n", 2190 timings->hsw, timings->hfp, timings->hbp, 2191 timings->vsw, timings->vfp, timings->vbp); 2192 2193 DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); 2194} 2195 2196static void dispc_set_lcd_divisor(u16 lck_div, u16 pck_div) 2197{ 2198 BUG_ON(lck_div < 1); 2199 BUG_ON(pck_div < 2); 2200 2201 enable_clocks(1); 2202 dispc_write_reg(DISPC_DIVISOR, 2203 FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); 2204 enable_clocks(0); 2205} 2206 2207static void dispc_get_lcd_divisor(int *lck_div, int *pck_div) 2208{ 2209 u32 l; 2210 l = dispc_read_reg(DISPC_DIVISOR); 2211 *lck_div = FLD_GET(l, 23, 16); 2212 *pck_div = FLD_GET(l, 7, 0); 2213} 2214 2215unsigned long dispc_fclk_rate(void) 2216{ 2217 unsigned long r = 0; 2218 2219 if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK) 2220 r = dss_clk_get_rate(DSS_CLK_FCK1); 2221 else 2222#ifdef CONFIG_OMAP2_DSS_DSI 2223 r = dsi_get_dsi1_pll_rate(); 2224#else 2225 BUG(); 2226#endif 2227 return r; 2228} 2229 2230unsigned long dispc_lclk_rate(void) 2231{ 2232 int lcd; 2233 unsigned long r; 2234 u32 l; 2235 2236 l = dispc_read_reg(DISPC_DIVISOR); 2237 2238 lcd = FLD_GET(l, 23, 16); 2239 2240 r = dispc_fclk_rate(); 2241 2242 return r / lcd; 2243} 2244 2245unsigned long dispc_pclk_rate(void) 2246{ 2247 int lcd, pcd; 2248 unsigned long r; 2249 u32 l; 2250 2251 l = dispc_read_reg(DISPC_DIVISOR); 2252 2253 lcd = FLD_GET(l, 23, 16); 2254 pcd = FLD_GET(l, 7, 0); 2255 2256 r = dispc_fclk_rate(); 2257 2258 return r / lcd / pcd; 2259} 2260 2261void dispc_dump_clocks(struct seq_file *s) 2262{ 2263 int lcd, pcd; 2264 2265 enable_clocks(1); 2266 2267 dispc_get_lcd_divisor(&lcd, &pcd); 2268 2269 seq_printf(s, "- DISPC -\n"); 2270 2271 seq_printf(s, "dispc fclk source = %s\n", 2272 dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ? 2273 "dss1_alwon_fclk" : "dsi1_pll_fclk"); 2274 2275 seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate()); 2276 seq_printf(s, "lck\t\t%-16lulck div\t%u\n", dispc_lclk_rate(), lcd); 2277 seq_printf(s, "pck\t\t%-16lupck div\t%u\n", dispc_pclk_rate(), pcd); 2278 2279 enable_clocks(0); 2280} 2281 2282#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 2283void dispc_dump_irqs(struct seq_file *s) 2284{ 2285 unsigned long flags; 2286 struct dispc_irq_stats stats; 2287 2288 spin_lock_irqsave(&dispc.irq_stats_lock, flags); 2289 2290 stats = dispc.irq_stats; 2291 memset(&dispc.irq_stats, 0, sizeof(dispc.irq_stats)); 2292 dispc.irq_stats.last_reset = jiffies; 2293 2294 spin_unlock_irqrestore(&dispc.irq_stats_lock, flags); 2295 2296 seq_printf(s, "period %u ms\n", 2297 jiffies_to_msecs(jiffies - stats.last_reset)); 2298 2299 seq_printf(s, "irqs %d\n", stats.irq_count); 2300#define PIS(x) \ 2301 seq_printf(s, "%-20s %10d\n", #x, stats.irqs[ffs(DISPC_IRQ_##x)-1]); 2302 2303 PIS(FRAMEDONE); 2304 PIS(VSYNC); 2305 PIS(EVSYNC_EVEN); 2306 PIS(EVSYNC_ODD); 2307 PIS(ACBIAS_COUNT_STAT); 2308 PIS(PROG_LINE_NUM); 2309 PIS(GFX_FIFO_UNDERFLOW); 2310 PIS(GFX_END_WIN); 2311 PIS(PAL_GAMMA_MASK); 2312 PIS(OCP_ERR); 2313 PIS(VID1_FIFO_UNDERFLOW); 2314 PIS(VID1_END_WIN); 2315 PIS(VID2_FIFO_UNDERFLOW); 2316 PIS(VID2_END_WIN); 2317 PIS(SYNC_LOST); 2318 PIS(SYNC_LOST_DIGIT); 2319 PIS(WAKEUP); 2320#undef PIS 2321} 2322#endif 2323 2324void dispc_dump_regs(struct seq_file *s) 2325{ 2326#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dispc_read_reg(r)) 2327 2328 dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1); 2329 2330 DUMPREG(DISPC_REVISION); 2331 DUMPREG(DISPC_SYSCONFIG); 2332 DUMPREG(DISPC_SYSSTATUS); 2333 DUMPREG(DISPC_IRQSTATUS); 2334 DUMPREG(DISPC_IRQENABLE); 2335 DUMPREG(DISPC_CONTROL); 2336 DUMPREG(DISPC_CONFIG); 2337 DUMPREG(DISPC_CAPABLE); 2338 DUMPREG(DISPC_DEFAULT_COLOR0); 2339 DUMPREG(DISPC_DEFAULT_COLOR1); 2340 DUMPREG(DISPC_TRANS_COLOR0); 2341 DUMPREG(DISPC_TRANS_COLOR1); 2342 DUMPREG(DISPC_LINE_STATUS); 2343 DUMPREG(DISPC_LINE_NUMBER); 2344 DUMPREG(DISPC_TIMING_H); 2345 DUMPREG(DISPC_TIMING_V); 2346 DUMPREG(DISPC_POL_FREQ); 2347 DUMPREG(DISPC_DIVISOR); 2348 DUMPREG(DISPC_GLOBAL_ALPHA); 2349 DUMPREG(DISPC_SIZE_DIG); 2350 DUMPREG(DISPC_SIZE_LCD); 2351 2352 DUMPREG(DISPC_GFX_BA0); 2353 DUMPREG(DISPC_GFX_BA1); 2354 DUMPREG(DISPC_GFX_POSITION); 2355 DUMPREG(DISPC_GFX_SIZE); 2356 DUMPREG(DISPC_GFX_ATTRIBUTES); 2357 DUMPREG(DISPC_GFX_FIFO_THRESHOLD); 2358 DUMPREG(DISPC_GFX_FIFO_SIZE_STATUS); 2359 DUMPREG(DISPC_GFX_ROW_INC); 2360 DUMPREG(DISPC_GFX_PIXEL_INC); 2361 DUMPREG(DISPC_GFX_WINDOW_SKIP); 2362 DUMPREG(DISPC_GFX_TABLE_BA); 2363 2364 DUMPREG(DISPC_DATA_CYCLE1); 2365 DUMPREG(DISPC_DATA_CYCLE2); 2366 DUMPREG(DISPC_DATA_CYCLE3); 2367 2368 DUMPREG(DISPC_CPR_COEF_R); 2369 DUMPREG(DISPC_CPR_COEF_G); 2370 DUMPREG(DISPC_CPR_COEF_B); 2371 2372 DUMPREG(DISPC_GFX_PRELOAD); 2373 2374 DUMPREG(DISPC_VID_BA0(0)); 2375 DUMPREG(DISPC_VID_BA1(0)); 2376 DUMPREG(DISPC_VID_POSITION(0)); 2377 DUMPREG(DISPC_VID_SIZE(0)); 2378 DUMPREG(DISPC_VID_ATTRIBUTES(0)); 2379 DUMPREG(DISPC_VID_FIFO_THRESHOLD(0)); 2380 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(0)); 2381 DUMPREG(DISPC_VID_ROW_INC(0)); 2382 DUMPREG(DISPC_VID_PIXEL_INC(0)); 2383 DUMPREG(DISPC_VID_FIR(0)); 2384 DUMPREG(DISPC_VID_PICTURE_SIZE(0)); 2385 DUMPREG(DISPC_VID_ACCU0(0)); 2386 DUMPREG(DISPC_VID_ACCU1(0)); 2387 2388 DUMPREG(DISPC_VID_BA0(1)); 2389 DUMPREG(DISPC_VID_BA1(1)); 2390 DUMPREG(DISPC_VID_POSITION(1)); 2391 DUMPREG(DISPC_VID_SIZE(1)); 2392 DUMPREG(DISPC_VID_ATTRIBUTES(1)); 2393 DUMPREG(DISPC_VID_FIFO_THRESHOLD(1)); 2394 DUMPREG(DISPC_VID_FIFO_SIZE_STATUS(1)); 2395 DUMPREG(DISPC_VID_ROW_INC(1)); 2396 DUMPREG(DISPC_VID_PIXEL_INC(1)); 2397 DUMPREG(DISPC_VID_FIR(1)); 2398 DUMPREG(DISPC_VID_PICTURE_SIZE(1)); 2399 DUMPREG(DISPC_VID_ACCU0(1)); 2400 DUMPREG(DISPC_VID_ACCU1(1)); 2401 2402 DUMPREG(DISPC_VID_FIR_COEF_H(0, 0)); 2403 DUMPREG(DISPC_VID_FIR_COEF_H(0, 1)); 2404 DUMPREG(DISPC_VID_FIR_COEF_H(0, 2)); 2405 DUMPREG(DISPC_VID_FIR_COEF_H(0, 3)); 2406 DUMPREG(DISPC_VID_FIR_COEF_H(0, 4)); 2407 DUMPREG(DISPC_VID_FIR_COEF_H(0, 5)); 2408 DUMPREG(DISPC_VID_FIR_COEF_H(0, 6)); 2409 DUMPREG(DISPC_VID_FIR_COEF_H(0, 7)); 2410 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 0)); 2411 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 1)); 2412 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 2)); 2413 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 3)); 2414 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 4)); 2415 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 5)); 2416 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 6)); 2417 DUMPREG(DISPC_VID_FIR_COEF_HV(0, 7)); 2418 DUMPREG(DISPC_VID_CONV_COEF(0, 0)); 2419 DUMPREG(DISPC_VID_CONV_COEF(0, 1)); 2420 DUMPREG(DISPC_VID_CONV_COEF(0, 2)); 2421 DUMPREG(DISPC_VID_CONV_COEF(0, 3)); 2422 DUMPREG(DISPC_VID_CONV_COEF(0, 4)); 2423 DUMPREG(DISPC_VID_FIR_COEF_V(0, 0)); 2424 DUMPREG(DISPC_VID_FIR_COEF_V(0, 1)); 2425 DUMPREG(DISPC_VID_FIR_COEF_V(0, 2)); 2426 DUMPREG(DISPC_VID_FIR_COEF_V(0, 3)); 2427 DUMPREG(DISPC_VID_FIR_COEF_V(0, 4)); 2428 DUMPREG(DISPC_VID_FIR_COEF_V(0, 5)); 2429 DUMPREG(DISPC_VID_FIR_COEF_V(0, 6)); 2430 DUMPREG(DISPC_VID_FIR_COEF_V(0, 7)); 2431 2432 DUMPREG(DISPC_VID_FIR_COEF_H(1, 0)); 2433 DUMPREG(DISPC_VID_FIR_COEF_H(1, 1)); 2434 DUMPREG(DISPC_VID_FIR_COEF_H(1, 2)); 2435 DUMPREG(DISPC_VID_FIR_COEF_H(1, 3)); 2436 DUMPREG(DISPC_VID_FIR_COEF_H(1, 4)); 2437 DUMPREG(DISPC_VID_FIR_COEF_H(1, 5)); 2438 DUMPREG(DISPC_VID_FIR_COEF_H(1, 6)); 2439 DUMPREG(DISPC_VID_FIR_COEF_H(1, 7)); 2440 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 0)); 2441 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 1)); 2442 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 2)); 2443 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 3)); 2444 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 4)); 2445 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 5)); 2446 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 6)); 2447 DUMPREG(DISPC_VID_FIR_COEF_HV(1, 7)); 2448 DUMPREG(DISPC_VID_CONV_COEF(1, 0)); 2449 DUMPREG(DISPC_VID_CONV_COEF(1, 1)); 2450 DUMPREG(DISPC_VID_CONV_COEF(1, 2)); 2451 DUMPREG(DISPC_VID_CONV_COEF(1, 3)); 2452 DUMPREG(DISPC_VID_CONV_COEF(1, 4)); 2453 DUMPREG(DISPC_VID_FIR_COEF_V(1, 0)); 2454 DUMPREG(DISPC_VID_FIR_COEF_V(1, 1)); 2455 DUMPREG(DISPC_VID_FIR_COEF_V(1, 2)); 2456 DUMPREG(DISPC_VID_FIR_COEF_V(1, 3)); 2457 DUMPREG(DISPC_VID_FIR_COEF_V(1, 4)); 2458 DUMPREG(DISPC_VID_FIR_COEF_V(1, 5)); 2459 DUMPREG(DISPC_VID_FIR_COEF_V(1, 6)); 2460 DUMPREG(DISPC_VID_FIR_COEF_V(1, 7)); 2461 2462 DUMPREG(DISPC_VID_PRELOAD(0)); 2463 DUMPREG(DISPC_VID_PRELOAD(1)); 2464 2465 dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1); 2466#undef DUMPREG 2467} 2468 2469static void _dispc_set_pol_freq(bool onoff, bool rf, bool ieo, bool ipc, 2470 bool ihs, bool ivs, u8 acbi, u8 acb) 2471{ 2472 u32 l = 0; 2473 2474 DSSDBG("onoff %d rf %d ieo %d ipc %d ihs %d ivs %d acbi %d acb %d\n", 2475 onoff, rf, ieo, ipc, ihs, ivs, acbi, acb); 2476 2477 l |= FLD_VAL(onoff, 17, 17); 2478 l |= FLD_VAL(rf, 16, 16); 2479 l |= FLD_VAL(ieo, 15, 15); 2480 l |= FLD_VAL(ipc, 14, 14); 2481 l |= FLD_VAL(ihs, 13, 13); 2482 l |= FLD_VAL(ivs, 12, 12); 2483 l |= FLD_VAL(acbi, 11, 8); 2484 l |= FLD_VAL(acb, 7, 0); 2485 2486 enable_clocks(1); 2487 dispc_write_reg(DISPC_POL_FREQ, l); 2488 enable_clocks(0); 2489} 2490 2491void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb) 2492{ 2493 _dispc_set_pol_freq((config & OMAP_DSS_LCD_ONOFF) != 0, 2494 (config & OMAP_DSS_LCD_RF) != 0, 2495 (config & OMAP_DSS_LCD_IEO) != 0, 2496 (config & OMAP_DSS_LCD_IPC) != 0, 2497 (config & OMAP_DSS_LCD_IHS) != 0, 2498 (config & OMAP_DSS_LCD_IVS) != 0, 2499 acbi, acb); 2500} 2501 2502/* with fck as input clock rate, find dispc dividers that produce req_pck */ 2503void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck, 2504 struct dispc_clock_info *cinfo) 2505{ 2506 u16 pcd_min = is_tft ? 2 : 3; 2507 unsigned long best_pck; 2508 u16 best_ld, cur_ld; 2509 u16 best_pd, cur_pd; 2510 2511 best_pck = 0; 2512 best_ld = 0; 2513 best_pd = 0; 2514 2515 for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { 2516 unsigned long lck = fck / cur_ld; 2517 2518 for (cur_pd = pcd_min; cur_pd <= 255; ++cur_pd) { 2519 unsigned long pck = lck / cur_pd; 2520 long old_delta = abs(best_pck - req_pck); 2521 long new_delta = abs(pck - req_pck); 2522 2523 if (best_pck == 0 || new_delta < old_delta) { 2524 best_pck = pck; 2525 best_ld = cur_ld; 2526 best_pd = cur_pd; 2527 2528 if (pck == req_pck) 2529 goto found; 2530 } 2531 2532 if (pck < req_pck) 2533 break; 2534 } 2535 2536 if (lck / pcd_min < req_pck) 2537 break; 2538 } 2539 2540found: 2541 cinfo->lck_div = best_ld; 2542 cinfo->pck_div = best_pd; 2543 cinfo->lck = fck / cinfo->lck_div; 2544 cinfo->pck = cinfo->lck / cinfo->pck_div; 2545} 2546 2547/* calculate clock rates using dividers in cinfo */ 2548int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, 2549 struct dispc_clock_info *cinfo) 2550{ 2551 if (cinfo->lck_div > 255 || cinfo->lck_div == 0) 2552 return -EINVAL; 2553 if (cinfo->pck_div < 2 || cinfo->pck_div > 255) 2554 return -EINVAL; 2555 2556 cinfo->lck = dispc_fclk_rate / cinfo->lck_div; 2557 cinfo->pck = cinfo->lck / cinfo->pck_div; 2558 2559 return 0; 2560} 2561 2562int dispc_set_clock_div(struct dispc_clock_info *cinfo) 2563{ 2564 DSSDBG("lck = %lu (%u)\n", cinfo->lck, cinfo->lck_div); 2565 DSSDBG("pck = %lu (%u)\n", cinfo->pck, cinfo->pck_div); 2566 2567 dispc_set_lcd_divisor(cinfo->lck_div, cinfo->pck_div); 2568 2569 return 0; 2570} 2571 2572int dispc_get_clock_div(struct dispc_clock_info *cinfo) 2573{ 2574 unsigned long fck; 2575 2576 fck = dispc_fclk_rate(); 2577 2578 cinfo->lck_div = REG_GET(DISPC_DIVISOR, 23, 16); 2579 cinfo->pck_div = REG_GET(DISPC_DIVISOR, 7, 0); 2580 2581 cinfo->lck = fck / cinfo->lck_div; 2582 cinfo->pck = cinfo->lck / cinfo->pck_div; 2583 2584 return 0; 2585} 2586 2587/* dispc.irq_lock has to be locked by the caller */ 2588static void _omap_dispc_set_irqs(void) 2589{ 2590 u32 mask; 2591 u32 old_mask; 2592 int i; 2593 struct omap_dispc_isr_data *isr_data; 2594 2595 mask = dispc.irq_error_mask; 2596 2597 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 2598 isr_data = &dispc.registered_isr[i]; 2599 2600 if (isr_data->isr == NULL) 2601 continue; 2602 2603 mask |= isr_data->mask; 2604 } 2605 2606 enable_clocks(1); 2607 2608 old_mask = dispc_read_reg(DISPC_IRQENABLE); 2609 /* clear the irqstatus for newly enabled irqs */ 2610 dispc_write_reg(DISPC_IRQSTATUS, (mask ^ old_mask) & mask); 2611 2612 dispc_write_reg(DISPC_IRQENABLE, mask); 2613 2614 enable_clocks(0); 2615} 2616 2617int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask) 2618{ 2619 int i; 2620 int ret; 2621 unsigned long flags; 2622 struct omap_dispc_isr_data *isr_data; 2623 2624 if (isr == NULL) 2625 return -EINVAL; 2626 2627 spin_lock_irqsave(&dispc.irq_lock, flags); 2628 2629 /* check for duplicate entry */ 2630 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 2631 isr_data = &dispc.registered_isr[i]; 2632 if (isr_data->isr == isr && isr_data->arg == arg && 2633 isr_data->mask == mask) { 2634 ret = -EINVAL; 2635 goto err; 2636 } 2637 } 2638 2639 isr_data = NULL; 2640 ret = -EBUSY; 2641 2642 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 2643 isr_data = &dispc.registered_isr[i]; 2644 2645 if (isr_data->isr != NULL) 2646 continue; 2647 2648 isr_data->isr = isr; 2649 isr_data->arg = arg; 2650 isr_data->mask = mask; 2651 ret = 0; 2652 2653 break; 2654 } 2655 2656 _omap_dispc_set_irqs(); 2657 2658 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2659 2660 return 0; 2661err: 2662 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2663 2664 return ret; 2665} 2666EXPORT_SYMBOL(omap_dispc_register_isr); 2667 2668int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask) 2669{ 2670 int i; 2671 unsigned long flags; 2672 int ret = -EINVAL; 2673 struct omap_dispc_isr_data *isr_data; 2674 2675 spin_lock_irqsave(&dispc.irq_lock, flags); 2676 2677 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 2678 isr_data = &dispc.registered_isr[i]; 2679 if (isr_data->isr != isr || isr_data->arg != arg || 2680 isr_data->mask != mask) 2681 continue; 2682 2683 /* found the correct isr */ 2684 2685 isr_data->isr = NULL; 2686 isr_data->arg = NULL; 2687 isr_data->mask = 0; 2688 2689 ret = 0; 2690 break; 2691 } 2692 2693 if (ret == 0) 2694 _omap_dispc_set_irqs(); 2695 2696 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2697 2698 return ret; 2699} 2700EXPORT_SYMBOL(omap_dispc_unregister_isr); 2701 2702#ifdef DEBUG 2703static void print_irq_status(u32 status) 2704{ 2705 if ((status & dispc.irq_error_mask) == 0) 2706 return; 2707 2708 printk(KERN_DEBUG "DISPC IRQ: 0x%x: ", status); 2709 2710#define PIS(x) \ 2711 if (status & DISPC_IRQ_##x) \ 2712 printk(#x " "); 2713 PIS(GFX_FIFO_UNDERFLOW); 2714 PIS(OCP_ERR); 2715 PIS(VID1_FIFO_UNDERFLOW); 2716 PIS(VID2_FIFO_UNDERFLOW); 2717 PIS(SYNC_LOST); 2718 PIS(SYNC_LOST_DIGIT); 2719#undef PIS 2720 2721 printk("\n"); 2722} 2723#endif 2724 2725/* Called from dss.c. Note that we don't touch clocks here, 2726 * but we presume they are on because we got an IRQ. However, 2727 * an irq handler may turn the clocks off, so we may not have 2728 * clock later in the function. */ 2729void dispc_irq_handler(void) 2730{ 2731 int i; 2732 u32 irqstatus; 2733 u32 handledirqs = 0; 2734 u32 unhandled_errors; 2735 struct omap_dispc_isr_data *isr_data; 2736 struct omap_dispc_isr_data registered_isr[DISPC_MAX_NR_ISRS]; 2737 2738 spin_lock(&dispc.irq_lock); 2739 2740 irqstatus = dispc_read_reg(DISPC_IRQSTATUS); 2741 2742#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 2743 spin_lock(&dispc.irq_stats_lock); 2744 dispc.irq_stats.irq_count++; 2745 dss_collect_irq_stats(irqstatus, dispc.irq_stats.irqs); 2746 spin_unlock(&dispc.irq_stats_lock); 2747#endif 2748 2749#ifdef DEBUG 2750 if (dss_debug) 2751 print_irq_status(irqstatus); 2752#endif 2753 /* Ack the interrupt. Do it here before clocks are possibly turned 2754 * off */ 2755 dispc_write_reg(DISPC_IRQSTATUS, irqstatus); 2756 /* flush posted write */ 2757 dispc_read_reg(DISPC_IRQSTATUS); 2758 2759 /* make a copy and unlock, so that isrs can unregister 2760 * themselves */ 2761 memcpy(registered_isr, dispc.registered_isr, 2762 sizeof(registered_isr)); 2763 2764 spin_unlock(&dispc.irq_lock); 2765 2766 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 2767 isr_data = ®istered_isr[i]; 2768 2769 if (!isr_data->isr) 2770 continue; 2771 2772 if (isr_data->mask & irqstatus) { 2773 isr_data->isr(isr_data->arg, irqstatus); 2774 handledirqs |= isr_data->mask; 2775 } 2776 } 2777 2778 spin_lock(&dispc.irq_lock); 2779 2780 unhandled_errors = irqstatus & ~handledirqs & dispc.irq_error_mask; 2781 2782 if (unhandled_errors) { 2783 dispc.error_irqs |= unhandled_errors; 2784 2785 dispc.irq_error_mask &= ~unhandled_errors; 2786 _omap_dispc_set_irqs(); 2787 2788 schedule_work(&dispc.error_work); 2789 } 2790 2791 spin_unlock(&dispc.irq_lock); 2792} 2793 2794static void dispc_error_worker(struct work_struct *work) 2795{ 2796 int i; 2797 u32 errors; 2798 unsigned long flags; 2799 2800 spin_lock_irqsave(&dispc.irq_lock, flags); 2801 errors = dispc.error_irqs; 2802 dispc.error_irqs = 0; 2803 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2804 2805 if (errors & DISPC_IRQ_GFX_FIFO_UNDERFLOW) { 2806 DSSERR("GFX_FIFO_UNDERFLOW, disabling GFX\n"); 2807 for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 2808 struct omap_overlay *ovl; 2809 ovl = omap_dss_get_overlay(i); 2810 2811 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) 2812 continue; 2813 2814 if (ovl->id == 0) { 2815 dispc_enable_plane(ovl->id, 0); 2816 dispc_go(ovl->manager->id); 2817 mdelay(50); 2818 break; 2819 } 2820 } 2821 } 2822 2823 if (errors & DISPC_IRQ_VID1_FIFO_UNDERFLOW) { 2824 DSSERR("VID1_FIFO_UNDERFLOW, disabling VID1\n"); 2825 for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 2826 struct omap_overlay *ovl; 2827 ovl = omap_dss_get_overlay(i); 2828 2829 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) 2830 continue; 2831 2832 if (ovl->id == 1) { 2833 dispc_enable_plane(ovl->id, 0); 2834 dispc_go(ovl->manager->id); 2835 mdelay(50); 2836 break; 2837 } 2838 } 2839 } 2840 2841 if (errors & DISPC_IRQ_VID2_FIFO_UNDERFLOW) { 2842 DSSERR("VID2_FIFO_UNDERFLOW, disabling VID2\n"); 2843 for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 2844 struct omap_overlay *ovl; 2845 ovl = omap_dss_get_overlay(i); 2846 2847 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) 2848 continue; 2849 2850 if (ovl->id == 2) { 2851 dispc_enable_plane(ovl->id, 0); 2852 dispc_go(ovl->manager->id); 2853 mdelay(50); 2854 break; 2855 } 2856 } 2857 } 2858 2859 if (errors & DISPC_IRQ_SYNC_LOST) { 2860 struct omap_overlay_manager *manager = NULL; 2861 bool enable = false; 2862 2863 DSSERR("SYNC_LOST, disabling LCD\n"); 2864 2865 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 2866 struct omap_overlay_manager *mgr; 2867 mgr = omap_dss_get_overlay_manager(i); 2868 2869 if (mgr->id == OMAP_DSS_CHANNEL_LCD) { 2870 manager = mgr; 2871 enable = mgr->device->state == 2872 OMAP_DSS_DISPLAY_ACTIVE; 2873 mgr->device->driver->disable(mgr->device); 2874 break; 2875 } 2876 } 2877 2878 if (manager) { 2879 struct omap_dss_device *dssdev = manager->device; 2880 for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 2881 struct omap_overlay *ovl; 2882 ovl = omap_dss_get_overlay(i); 2883 2884 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) 2885 continue; 2886 2887 if (ovl->id != 0 && ovl->manager == manager) 2888 dispc_enable_plane(ovl->id, 0); 2889 } 2890 2891 dispc_go(manager->id); 2892 mdelay(50); 2893 if (enable) 2894 dssdev->driver->enable(dssdev); 2895 } 2896 } 2897 2898 if (errors & DISPC_IRQ_SYNC_LOST_DIGIT) { 2899 struct omap_overlay_manager *manager = NULL; 2900 bool enable = false; 2901 2902 DSSERR("SYNC_LOST_DIGIT, disabling TV\n"); 2903 2904 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 2905 struct omap_overlay_manager *mgr; 2906 mgr = omap_dss_get_overlay_manager(i); 2907 2908 if (mgr->id == OMAP_DSS_CHANNEL_DIGIT) { 2909 manager = mgr; 2910 enable = mgr->device->state == 2911 OMAP_DSS_DISPLAY_ACTIVE; 2912 mgr->device->driver->disable(mgr->device); 2913 break; 2914 } 2915 } 2916 2917 if (manager) { 2918 struct omap_dss_device *dssdev = manager->device; 2919 for (i = 0; i < omap_dss_get_num_overlays(); ++i) { 2920 struct omap_overlay *ovl; 2921 ovl = omap_dss_get_overlay(i); 2922 2923 if (!(ovl->caps & OMAP_DSS_OVL_CAP_DISPC)) 2924 continue; 2925 2926 if (ovl->id != 0 && ovl->manager == manager) 2927 dispc_enable_plane(ovl->id, 0); 2928 } 2929 2930 dispc_go(manager->id); 2931 mdelay(50); 2932 if (enable) 2933 dssdev->driver->enable(dssdev); 2934 } 2935 } 2936 2937 if (errors & DISPC_IRQ_OCP_ERR) { 2938 DSSERR("OCP_ERR\n"); 2939 for (i = 0; i < omap_dss_get_num_overlay_managers(); ++i) { 2940 struct omap_overlay_manager *mgr; 2941 mgr = omap_dss_get_overlay_manager(i); 2942 2943 if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC) 2944 mgr->device->driver->disable(mgr->device); 2945 } 2946 } 2947 2948 spin_lock_irqsave(&dispc.irq_lock, flags); 2949 dispc.irq_error_mask |= errors; 2950 _omap_dispc_set_irqs(); 2951 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2952} 2953 2954int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout) 2955{ 2956 void dispc_irq_wait_handler(void *data, u32 mask) 2957 { 2958 complete((struct completion *)data); 2959 } 2960 2961 int r; 2962 DECLARE_COMPLETION_ONSTACK(completion); 2963 2964 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, 2965 irqmask); 2966 2967 if (r) 2968 return r; 2969 2970 timeout = wait_for_completion_timeout(&completion, timeout); 2971 2972 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); 2973 2974 if (timeout == 0) 2975 return -ETIMEDOUT; 2976 2977 if (timeout == -ERESTARTSYS) 2978 return -ERESTARTSYS; 2979 2980 return 0; 2981} 2982 2983int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask, 2984 unsigned long timeout) 2985{ 2986 void dispc_irq_wait_handler(void *data, u32 mask) 2987 { 2988 complete((struct completion *)data); 2989 } 2990 2991 int r; 2992 DECLARE_COMPLETION_ONSTACK(completion); 2993 2994 r = omap_dispc_register_isr(dispc_irq_wait_handler, &completion, 2995 irqmask); 2996 2997 if (r) 2998 return r; 2999 3000 timeout = wait_for_completion_interruptible_timeout(&completion, 3001 timeout); 3002 3003 omap_dispc_unregister_isr(dispc_irq_wait_handler, &completion, irqmask); 3004 3005 if (timeout == 0) 3006 return -ETIMEDOUT; 3007 3008 if (timeout == -ERESTARTSYS) 3009 return -ERESTARTSYS; 3010 3011 return 0; 3012} 3013 3014#ifdef CONFIG_OMAP2_DSS_FAKE_VSYNC 3015void dispc_fake_vsync_irq(void) 3016{ 3017 u32 irqstatus = DISPC_IRQ_VSYNC; 3018 int i; 3019 3020 WARN_ON(!in_interrupt()); 3021 3022 for (i = 0; i < DISPC_MAX_NR_ISRS; i++) { 3023 struct omap_dispc_isr_data *isr_data; 3024 isr_data = &dispc.registered_isr[i]; 3025 3026 if (!isr_data->isr) 3027 continue; 3028 3029 if (isr_data->mask & irqstatus) 3030 isr_data->isr(isr_data->arg, irqstatus); 3031 } 3032} 3033#endif 3034 3035static void _omap_dispc_initialize_irq(void) 3036{ 3037 unsigned long flags; 3038 3039 spin_lock_irqsave(&dispc.irq_lock, flags); 3040 3041 memset(dispc.registered_isr, 0, sizeof(dispc.registered_isr)); 3042 3043 dispc.irq_error_mask = DISPC_IRQ_MASK_ERROR; 3044 3045 /* there's SYNC_LOST_DIGIT waiting after enabling the DSS, 3046 * so clear it */ 3047 dispc_write_reg(DISPC_IRQSTATUS, dispc_read_reg(DISPC_IRQSTATUS)); 3048 3049 _omap_dispc_set_irqs(); 3050 3051 spin_unlock_irqrestore(&dispc.irq_lock, flags); 3052} 3053 3054void dispc_enable_sidle(void) 3055{ 3056 REG_FLD_MOD(DISPC_SYSCONFIG, 2, 4, 3); /* SIDLEMODE: smart idle */ 3057} 3058 3059void dispc_disable_sidle(void) 3060{ 3061 REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */ 3062} 3063 3064static void _omap_dispc_initial_config(void) 3065{ 3066 u32 l; 3067 3068 l = dispc_read_reg(DISPC_SYSCONFIG); 3069 l = FLD_MOD(l, 2, 13, 12); /* MIDLEMODE: smart standby */ 3070 l = FLD_MOD(l, 2, 4, 3); /* SIDLEMODE: smart idle */ 3071 l = FLD_MOD(l, 1, 2, 2); /* ENWAKEUP */ 3072 l = FLD_MOD(l, 1, 0, 0); /* AUTOIDLE */ 3073 dispc_write_reg(DISPC_SYSCONFIG, l); 3074 3075 /* FUNCGATED */ 3076 REG_FLD_MOD(DISPC_CONFIG, 1, 9, 9); 3077 3078 /* L3 firewall setting: enable access to OCM RAM */ 3079 if (cpu_is_omap24xx()) 3080 __raw_writel(0x402000b0, OMAP2_L3_IO_ADDRESS(0x680050a0)); 3081 3082 _dispc_setup_color_conv_coef(); 3083 3084 dispc_set_loadmode(OMAP_DSS_LOAD_FRAME_ONLY); 3085 3086 dispc_read_plane_fifo_sizes(); 3087} 3088 3089int dispc_init(void) 3090{ 3091 u32 rev; 3092 3093 spin_lock_init(&dispc.irq_lock); 3094 3095#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS 3096 spin_lock_init(&dispc.irq_stats_lock); 3097 dispc.irq_stats.last_reset = jiffies; 3098#endif 3099 3100 INIT_WORK(&dispc.error_work, dispc_error_worker); 3101 3102 dispc.base = ioremap(DISPC_BASE, DISPC_SZ_REGS); 3103 if (!dispc.base) { 3104 DSSERR("can't ioremap DISPC\n"); 3105 return -ENOMEM; 3106 } 3107 3108 enable_clocks(1); 3109 3110 _omap_dispc_initial_config(); 3111 3112 _omap_dispc_initialize_irq(); 3113 3114 dispc_save_context(); 3115 3116 rev = dispc_read_reg(DISPC_REVISION); 3117 printk(KERN_INFO "OMAP DISPC rev %d.%d\n", 3118 FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); 3119 3120 enable_clocks(0); 3121 3122 return 0; 3123} 3124 3125void dispc_exit(void) 3126{ 3127 iounmap(dispc.base); 3128} 3129 3130int dispc_enable_plane(enum omap_plane plane, bool enable) 3131{ 3132 DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); 3133 3134 enable_clocks(1); 3135 _dispc_enable_plane(plane, enable); 3136 enable_clocks(0); 3137 3138 return 0; 3139} 3140 3141int dispc_setup_plane(enum omap_plane plane, 3142 u32 paddr, u16 screen_width, 3143 u16 pos_x, u16 pos_y, 3144 u16 width, u16 height, 3145 u16 out_width, u16 out_height, 3146 enum omap_color_mode color_mode, 3147 bool ilace, 3148 enum omap_dss_rotation_type rotation_type, 3149 u8 rotation, bool mirror, u8 global_alpha) 3150{ 3151 int r = 0; 3152 3153 DSSDBG("dispc_setup_plane %d, pa %x, sw %d, %d,%d, %dx%d -> " 3154 "%dx%d, ilace %d, cmode %x, rot %d, mir %d\n", 3155 plane, paddr, screen_width, pos_x, pos_y, 3156 width, height, 3157 out_width, out_height, 3158 ilace, color_mode, 3159 rotation, mirror); 3160 3161 enable_clocks(1); 3162 3163 r = _dispc_setup_plane(plane, 3164 paddr, screen_width, 3165 pos_x, pos_y, 3166 width, height, 3167 out_width, out_height, 3168 color_mode, ilace, 3169 rotation_type, 3170 rotation, mirror, 3171 global_alpha); 3172 3173 enable_clocks(0); 3174 3175 return r; 3176} 3177