1/* 2 * Copyright (C) 2007-2010 Texas Instruments Inc 3 * Copyright (C) 2007 MontaVista Software, Inc. 4 * 5 * Andy Lowe (alowe@mvista.com), MontaVista Software 6 * - Initial version 7 * Murali Karicheri (mkaricheri@gmail.com), Texas Instruments Ltd. 8 * - ported to sub device interface 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation version 2. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * 23 */ 24#include <linux/module.h> 25#include <linux/kernel.h> 26#include <linux/interrupt.h> 27#include <linux/platform_device.h> 28#include <linux/clk.h> 29#include <linux/slab.h> 30 31#include <mach/io.h> 32#include <mach/cputype.h> 33#include <mach/hardware.h> 34 35#include <media/davinci/vpss.h> 36#include <media/v4l2-device.h> 37#include <media/davinci/vpbe_types.h> 38#include <media/davinci/vpbe_osd.h> 39 40#include <linux/io.h> 41#include "vpbe_osd_regs.h" 42 43#define MODULE_NAME VPBE_OSD_SUBDEV_NAME 44 45/* register access routines */ 46static inline u32 osd_read(struct osd_state *sd, u32 offset) 47{ 48 struct osd_state *osd = sd; 49 50 return readl(osd->osd_base + offset); 51} 52 53static inline u32 osd_write(struct osd_state *sd, u32 val, u32 offset) 54{ 55 struct osd_state *osd = sd; 56 57 writel(val, osd->osd_base + offset); 58 59 return val; 60} 61 62static inline u32 osd_set(struct osd_state *sd, u32 mask, u32 offset) 63{ 64 struct osd_state *osd = sd; 65 66 u32 addr = osd->osd_base + offset; 67 u32 val = readl(addr) | mask; 68 69 writel(val, addr); 70 71 return val; 72} 73 74static inline u32 osd_clear(struct osd_state *sd, u32 mask, u32 offset) 75{ 76 struct osd_state *osd = sd; 77 78 u32 addr = osd->osd_base + offset; 79 u32 val = readl(addr) & ~mask; 80 81 writel(val, addr); 82 83 return val; 84} 85 86static inline u32 osd_modify(struct osd_state *sd, u32 mask, u32 val, 87 u32 offset) 88{ 89 struct osd_state *osd = sd; 90 91 u32 addr = osd->osd_base + offset; 92 u32 new_val = (readl(addr) & ~mask) | (val & mask); 93 94 writel(new_val, addr); 95 96 return new_val; 97} 98 99/* define some macros for layer and pixfmt classification */ 100#define is_osd_win(layer) (((layer) == WIN_OSD0) || ((layer) == WIN_OSD1)) 101#define is_vid_win(layer) (((layer) == WIN_VID0) || ((layer) == WIN_VID1)) 102#define is_rgb_pixfmt(pixfmt) \ 103 (((pixfmt) == PIXFMT_RGB565) || ((pixfmt) == PIXFMT_RGB888)) 104#define is_yc_pixfmt(pixfmt) \ 105 (((pixfmt) == PIXFMT_YCbCrI) || ((pixfmt) == PIXFMT_YCrCbI) || \ 106 ((pixfmt) == PIXFMT_NV12)) 107#define MAX_WIN_SIZE OSD_VIDWIN0XP_V0X 108#define MAX_LINE_LENGTH (OSD_VIDWIN0OFST_V0LO << 5) 109 110/** 111 * _osd_dm6446_vid0_pingpong() - field inversion fix for DM6446 112 * @sd - ptr to struct osd_state 113 * @field_inversion - inversion flag 114 * @fb_base_phys - frame buffer address 115 * @lconfig - ptr to layer config 116 * 117 * This routine implements a workaround for the field signal inversion silicon 118 * erratum described in Advisory 1.3.8 for the DM6446. The fb_base_phys and 119 * lconfig parameters apply to the vid0 window. This routine should be called 120 * whenever the vid0 layer configuration or start address is modified, or when 121 * the OSD field inversion setting is modified. 122 * Returns: 1 if the ping-pong buffers need to be toggled in the vsync isr, or 123 * 0 otherwise 124 */ 125static int _osd_dm6446_vid0_pingpong(struct osd_state *sd, 126 int field_inversion, 127 unsigned long fb_base_phys, 128 const struct osd_layer_config *lconfig) 129{ 130 struct osd_platform_data *pdata; 131 132 pdata = (struct osd_platform_data *)sd->dev->platform_data; 133 if (pdata->field_inv_wa_enable) { 134 135 if (!field_inversion || !lconfig->interlaced) { 136 osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR); 137 osd_write(sd, fb_base_phys & ~0x1F, OSD_PPVWIN0ADR); 138 osd_modify(sd, OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, 0, 139 OSD_MISCCTL); 140 return 0; 141 } else { 142 unsigned miscctl = OSD_MISCCTL_PPRV; 143 144 osd_write(sd, 145 (fb_base_phys & ~0x1F) - lconfig->line_length, 146 OSD_VIDWIN0ADR); 147 osd_write(sd, 148 (fb_base_phys & ~0x1F) + lconfig->line_length, 149 OSD_PPVWIN0ADR); 150 osd_modify(sd, 151 OSD_MISCCTL_PPSW | OSD_MISCCTL_PPRV, miscctl, 152 OSD_MISCCTL); 153 154 return 1; 155 } 156 } 157 158 return 0; 159} 160 161static void _osd_set_field_inversion(struct osd_state *sd, int enable) 162{ 163 unsigned fsinv = 0; 164 165 if (enable) 166 fsinv = OSD_MODE_FSINV; 167 168 osd_modify(sd, OSD_MODE_FSINV, fsinv, OSD_MODE); 169} 170 171static void _osd_set_blink_attribute(struct osd_state *sd, int enable, 172 enum osd_blink_interval blink) 173{ 174 u32 osdatrmd = 0; 175 176 if (enable) { 177 osdatrmd |= OSD_OSDATRMD_BLNK; 178 osdatrmd |= blink << OSD_OSDATRMD_BLNKINT_SHIFT; 179 } 180 /* caller must ensure that OSD1 is configured in attribute mode */ 181 osd_modify(sd, OSD_OSDATRMD_BLNKINT | OSD_OSDATRMD_BLNK, osdatrmd, 182 OSD_OSDATRMD); 183} 184 185static void _osd_set_rom_clut(struct osd_state *sd, 186 enum osd_rom_clut rom_clut) 187{ 188 if (rom_clut == ROM_CLUT0) 189 osd_clear(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL); 190 else 191 osd_set(sd, OSD_MISCCTL_RSEL, OSD_MISCCTL); 192} 193 194static void _osd_set_palette_map(struct osd_state *sd, 195 enum osd_win_layer osdwin, 196 unsigned char pixel_value, 197 unsigned char clut_index, 198 enum osd_pix_format pixfmt) 199{ 200 static const int map_2bpp[] = { 0, 5, 10, 15 }; 201 static const int map_1bpp[] = { 0, 15 }; 202 int bmp_offset; 203 int bmp_shift; 204 int bmp_mask; 205 int bmp_reg; 206 207 switch (pixfmt) { 208 case PIXFMT_1BPP: 209 bmp_reg = map_1bpp[pixel_value & 0x1]; 210 break; 211 case PIXFMT_2BPP: 212 bmp_reg = map_2bpp[pixel_value & 0x3]; 213 break; 214 case PIXFMT_4BPP: 215 bmp_reg = pixel_value & 0xf; 216 break; 217 default: 218 return; 219 } 220 221 switch (osdwin) { 222 case OSDWIN_OSD0: 223 bmp_offset = OSD_W0BMP01 + (bmp_reg >> 1) * sizeof(u32); 224 break; 225 case OSDWIN_OSD1: 226 bmp_offset = OSD_W1BMP01 + (bmp_reg >> 1) * sizeof(u32); 227 break; 228 default: 229 return; 230 } 231 232 if (bmp_reg & 1) { 233 bmp_shift = 8; 234 bmp_mask = 0xff << 8; 235 } else { 236 bmp_shift = 0; 237 bmp_mask = 0xff; 238 } 239 240 osd_modify(sd, bmp_mask, clut_index << bmp_shift, bmp_offset); 241} 242 243static void _osd_set_rec601_attenuation(struct osd_state *sd, 244 enum osd_win_layer osdwin, int enable) 245{ 246 switch (osdwin) { 247 case OSDWIN_OSD0: 248 osd_modify(sd, OSD_OSDWIN0MD_ATN0E, 249 enable ? OSD_OSDWIN0MD_ATN0E : 0, 250 OSD_OSDWIN0MD); 251 if (sd->vpbe_type == VPBE_VERSION_1) 252 osd_modify(sd, OSD_OSDWIN0MD_ATN0E, 253 enable ? OSD_OSDWIN0MD_ATN0E : 0, 254 OSD_OSDWIN0MD); 255 else if ((sd->vpbe_type == VPBE_VERSION_3) || 256 (sd->vpbe_type == VPBE_VERSION_2)) 257 osd_modify(sd, OSD_EXTMODE_ATNOSD0EN, 258 enable ? OSD_EXTMODE_ATNOSD0EN : 0, 259 OSD_EXTMODE); 260 break; 261 case OSDWIN_OSD1: 262 osd_modify(sd, OSD_OSDWIN1MD_ATN1E, 263 enable ? OSD_OSDWIN1MD_ATN1E : 0, 264 OSD_OSDWIN1MD); 265 if (sd->vpbe_type == VPBE_VERSION_1) 266 osd_modify(sd, OSD_OSDWIN1MD_ATN1E, 267 enable ? OSD_OSDWIN1MD_ATN1E : 0, 268 OSD_OSDWIN1MD); 269 else if ((sd->vpbe_type == VPBE_VERSION_3) || 270 (sd->vpbe_type == VPBE_VERSION_2)) 271 osd_modify(sd, OSD_EXTMODE_ATNOSD1EN, 272 enable ? OSD_EXTMODE_ATNOSD1EN : 0, 273 OSD_EXTMODE); 274 break; 275 } 276} 277 278static void _osd_set_blending_factor(struct osd_state *sd, 279 enum osd_win_layer osdwin, 280 enum osd_blending_factor blend) 281{ 282 switch (osdwin) { 283 case OSDWIN_OSD0: 284 osd_modify(sd, OSD_OSDWIN0MD_BLND0, 285 blend << OSD_OSDWIN0MD_BLND0_SHIFT, OSD_OSDWIN0MD); 286 break; 287 case OSDWIN_OSD1: 288 osd_modify(sd, OSD_OSDWIN1MD_BLND1, 289 blend << OSD_OSDWIN1MD_BLND1_SHIFT, OSD_OSDWIN1MD); 290 break; 291 } 292} 293 294static void _osd_enable_rgb888_pixblend(struct osd_state *sd, 295 enum osd_win_layer osdwin) 296{ 297 298 osd_modify(sd, OSD_MISCCTL_BLDSEL, 0, OSD_MISCCTL); 299 switch (osdwin) { 300 case OSDWIN_OSD0: 301 osd_modify(sd, OSD_EXTMODE_OSD0BLDCHR, 302 OSD_EXTMODE_OSD0BLDCHR, OSD_EXTMODE); 303 break; 304 case OSDWIN_OSD1: 305 osd_modify(sd, OSD_EXTMODE_OSD1BLDCHR, 306 OSD_EXTMODE_OSD1BLDCHR, OSD_EXTMODE); 307 break; 308 } 309} 310 311static void _osd_enable_color_key(struct osd_state *sd, 312 enum osd_win_layer osdwin, 313 unsigned colorkey, 314 enum osd_pix_format pixfmt) 315{ 316 switch (pixfmt) { 317 case PIXFMT_1BPP: 318 case PIXFMT_2BPP: 319 case PIXFMT_4BPP: 320 case PIXFMT_8BPP: 321 if (sd->vpbe_type == VPBE_VERSION_3) { 322 switch (osdwin) { 323 case OSDWIN_OSD0: 324 osd_modify(sd, OSD_TRANSPBMPIDX_BMP0, 325 colorkey << 326 OSD_TRANSPBMPIDX_BMP0_SHIFT, 327 OSD_TRANSPBMPIDX); 328 break; 329 case OSDWIN_OSD1: 330 osd_modify(sd, OSD_TRANSPBMPIDX_BMP1, 331 colorkey << 332 OSD_TRANSPBMPIDX_BMP1_SHIFT, 333 OSD_TRANSPBMPIDX); 334 break; 335 } 336 } 337 break; 338 case PIXFMT_RGB565: 339 if (sd->vpbe_type == VPBE_VERSION_1) 340 osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS, 341 OSD_TRANSPVAL); 342 else if (sd->vpbe_type == VPBE_VERSION_3) 343 osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL, 344 OSD_TRANSPVALL); 345 break; 346 case PIXFMT_YCbCrI: 347 case PIXFMT_YCrCbI: 348 if (sd->vpbe_type == VPBE_VERSION_3) 349 osd_modify(sd, OSD_TRANSPVALU_Y, colorkey, 350 OSD_TRANSPVALU); 351 break; 352 case PIXFMT_RGB888: 353 if (sd->vpbe_type == VPBE_VERSION_3) { 354 osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL, 355 OSD_TRANSPVALL); 356 osd_modify(sd, OSD_TRANSPVALU_RGBU, colorkey >> 16, 357 OSD_TRANSPVALU); 358 } 359 break; 360 default: 361 break; 362 } 363 364 switch (osdwin) { 365 case OSDWIN_OSD0: 366 osd_set(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD); 367 break; 368 case OSDWIN_OSD1: 369 osd_set(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD); 370 break; 371 } 372} 373 374static void _osd_disable_color_key(struct osd_state *sd, 375 enum osd_win_layer osdwin) 376{ 377 switch (osdwin) { 378 case OSDWIN_OSD0: 379 osd_clear(sd, OSD_OSDWIN0MD_TE0, OSD_OSDWIN0MD); 380 break; 381 case OSDWIN_OSD1: 382 osd_clear(sd, OSD_OSDWIN1MD_TE1, OSD_OSDWIN1MD); 383 break; 384 } 385} 386 387static void _osd_set_osd_clut(struct osd_state *sd, 388 enum osd_win_layer osdwin, 389 enum osd_clut clut) 390{ 391 u32 winmd = 0; 392 393 switch (osdwin) { 394 case OSDWIN_OSD0: 395 if (clut == RAM_CLUT) 396 winmd |= OSD_OSDWIN0MD_CLUTS0; 397 osd_modify(sd, OSD_OSDWIN0MD_CLUTS0, winmd, OSD_OSDWIN0MD); 398 break; 399 case OSDWIN_OSD1: 400 if (clut == RAM_CLUT) 401 winmd |= OSD_OSDWIN1MD_CLUTS1; 402 osd_modify(sd, OSD_OSDWIN1MD_CLUTS1, winmd, OSD_OSDWIN1MD); 403 break; 404 } 405} 406 407static void _osd_set_zoom(struct osd_state *sd, enum osd_layer layer, 408 enum osd_zoom_factor h_zoom, 409 enum osd_zoom_factor v_zoom) 410{ 411 u32 winmd = 0; 412 413 switch (layer) { 414 case WIN_OSD0: 415 winmd |= (h_zoom << OSD_OSDWIN0MD_OHZ0_SHIFT); 416 winmd |= (v_zoom << OSD_OSDWIN0MD_OVZ0_SHIFT); 417 osd_modify(sd, OSD_OSDWIN0MD_OHZ0 | OSD_OSDWIN0MD_OVZ0, winmd, 418 OSD_OSDWIN0MD); 419 break; 420 case WIN_VID0: 421 winmd |= (h_zoom << OSD_VIDWINMD_VHZ0_SHIFT); 422 winmd |= (v_zoom << OSD_VIDWINMD_VVZ0_SHIFT); 423 osd_modify(sd, OSD_VIDWINMD_VHZ0 | OSD_VIDWINMD_VVZ0, winmd, 424 OSD_VIDWINMD); 425 break; 426 case WIN_OSD1: 427 winmd |= (h_zoom << OSD_OSDWIN1MD_OHZ1_SHIFT); 428 winmd |= (v_zoom << OSD_OSDWIN1MD_OVZ1_SHIFT); 429 osd_modify(sd, OSD_OSDWIN1MD_OHZ1 | OSD_OSDWIN1MD_OVZ1, winmd, 430 OSD_OSDWIN1MD); 431 break; 432 case WIN_VID1: 433 winmd |= (h_zoom << OSD_VIDWINMD_VHZ1_SHIFT); 434 winmd |= (v_zoom << OSD_VIDWINMD_VVZ1_SHIFT); 435 osd_modify(sd, OSD_VIDWINMD_VHZ1 | OSD_VIDWINMD_VVZ1, winmd, 436 OSD_VIDWINMD); 437 break; 438 } 439} 440 441static void _osd_disable_layer(struct osd_state *sd, enum osd_layer layer) 442{ 443 switch (layer) { 444 case WIN_OSD0: 445 osd_clear(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD); 446 break; 447 case WIN_VID0: 448 osd_clear(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD); 449 break; 450 case WIN_OSD1: 451 /* disable attribute mode as well as disabling the window */ 452 osd_clear(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1, 453 OSD_OSDWIN1MD); 454 break; 455 case WIN_VID1: 456 osd_clear(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD); 457 break; 458 } 459} 460 461static void osd_disable_layer(struct osd_state *sd, enum osd_layer layer) 462{ 463 struct osd_state *osd = sd; 464 struct osd_window_state *win = &osd->win[layer]; 465 unsigned long flags; 466 467 spin_lock_irqsave(&osd->lock, flags); 468 469 if (!win->is_enabled) { 470 spin_unlock_irqrestore(&osd->lock, flags); 471 return; 472 } 473 win->is_enabled = 0; 474 475 _osd_disable_layer(sd, layer); 476 477 spin_unlock_irqrestore(&osd->lock, flags); 478} 479 480static void _osd_enable_attribute_mode(struct osd_state *sd) 481{ 482 /* enable attribute mode for OSD1 */ 483 osd_set(sd, OSD_OSDWIN1MD_OASW, OSD_OSDWIN1MD); 484} 485 486static void _osd_enable_layer(struct osd_state *sd, enum osd_layer layer) 487{ 488 switch (layer) { 489 case WIN_OSD0: 490 osd_set(sd, OSD_OSDWIN0MD_OACT0, OSD_OSDWIN0MD); 491 break; 492 case WIN_VID0: 493 osd_set(sd, OSD_VIDWINMD_ACT0, OSD_VIDWINMD); 494 break; 495 case WIN_OSD1: 496 /* enable OSD1 and disable attribute mode */ 497 osd_modify(sd, OSD_OSDWIN1MD_OASW | OSD_OSDWIN1MD_OACT1, 498 OSD_OSDWIN1MD_OACT1, OSD_OSDWIN1MD); 499 break; 500 case WIN_VID1: 501 osd_set(sd, OSD_VIDWINMD_ACT1, OSD_VIDWINMD); 502 break; 503 } 504} 505 506static int osd_enable_layer(struct osd_state *sd, enum osd_layer layer, 507 int otherwin) 508{ 509 struct osd_state *osd = sd; 510 struct osd_window_state *win = &osd->win[layer]; 511 struct osd_layer_config *cfg = &win->lconfig; 512 unsigned long flags; 513 514 spin_lock_irqsave(&osd->lock, flags); 515 516 /* 517 * use otherwin flag to know this is the other vid window 518 * in YUV420 mode, if is, skip this check 519 */ 520 if (!otherwin && (!win->is_allocated || 521 !win->fb_base_phys || 522 !cfg->line_length || 523 !cfg->xsize || 524 !cfg->ysize)) { 525 spin_unlock_irqrestore(&osd->lock, flags); 526 return -1; 527 } 528 529 if (win->is_enabled) { 530 spin_unlock_irqrestore(&osd->lock, flags); 531 return 0; 532 } 533 win->is_enabled = 1; 534 535 if (cfg->pixfmt != PIXFMT_OSD_ATTR) 536 _osd_enable_layer(sd, layer); 537 else { 538 _osd_enable_attribute_mode(sd); 539 _osd_set_blink_attribute(sd, osd->is_blinking, osd->blink); 540 } 541 542 spin_unlock_irqrestore(&osd->lock, flags); 543 544 return 0; 545} 546 547#define OSD_SRC_ADDR_HIGH4 0x7800000 548#define OSD_SRC_ADDR_HIGH7 0x7F0000 549#define OSD_SRCADD_OFSET_SFT 23 550#define OSD_SRCADD_ADD_SFT 16 551#define OSD_WINADL_MASK 0xFFFF 552#define OSD_WINOFST_MASK 0x1000 553#define VPBE_REG_BASE 0x80000000 554 555static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer, 556 unsigned long fb_base_phys, 557 unsigned long cbcr_ofst) 558{ 559 560 if (sd->vpbe_type == VPBE_VERSION_1) { 561 switch (layer) { 562 case WIN_OSD0: 563 osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR); 564 break; 565 case WIN_VID0: 566 osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR); 567 break; 568 case WIN_OSD1: 569 osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR); 570 break; 571 case WIN_VID1: 572 osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR); 573 break; 574 } 575 } else if (sd->vpbe_type == VPBE_VERSION_3) { 576 unsigned long fb_offset_32 = 577 (fb_base_phys - VPBE_REG_BASE) >> 5; 578 579 switch (layer) { 580 case WIN_OSD0: 581 osd_modify(sd, OSD_OSDWINADH_O0AH, 582 fb_offset_32 >> (OSD_SRCADD_ADD_SFT - 583 OSD_OSDWINADH_O0AH_SHIFT), 584 OSD_OSDWINADH); 585 osd_write(sd, fb_offset_32 & OSD_OSDWIN0ADL_O0AL, 586 OSD_OSDWIN0ADL); 587 break; 588 case WIN_VID0: 589 osd_modify(sd, OSD_VIDWINADH_V0AH, 590 fb_offset_32 >> (OSD_SRCADD_ADD_SFT - 591 OSD_VIDWINADH_V0AH_SHIFT), 592 OSD_VIDWINADH); 593 osd_write(sd, fb_offset_32 & OSD_VIDWIN0ADL_V0AL, 594 OSD_VIDWIN0ADL); 595 break; 596 case WIN_OSD1: 597 osd_modify(sd, OSD_OSDWINADH_O1AH, 598 fb_offset_32 >> (OSD_SRCADD_ADD_SFT - 599 OSD_OSDWINADH_O1AH_SHIFT), 600 OSD_OSDWINADH); 601 osd_write(sd, fb_offset_32 & OSD_OSDWIN1ADL_O1AL, 602 OSD_OSDWIN1ADL); 603 break; 604 case WIN_VID1: 605 osd_modify(sd, OSD_VIDWINADH_V1AH, 606 fb_offset_32 >> (OSD_SRCADD_ADD_SFT - 607 OSD_VIDWINADH_V1AH_SHIFT), 608 OSD_VIDWINADH); 609 osd_write(sd, fb_offset_32 & OSD_VIDWIN1ADL_V1AL, 610 OSD_VIDWIN1ADL); 611 break; 612 } 613 } else if (sd->vpbe_type == VPBE_VERSION_2) { 614 struct osd_window_state *win = &sd->win[layer]; 615 unsigned long fb_offset_32, cbcr_offset_32; 616 617 fb_offset_32 = fb_base_phys - VPBE_REG_BASE; 618 if (cbcr_ofst) 619 cbcr_offset_32 = cbcr_ofst; 620 else 621 cbcr_offset_32 = win->lconfig.line_length * 622 win->lconfig.ysize; 623 cbcr_offset_32 += fb_offset_32; 624 fb_offset_32 = fb_offset_32 >> 5; 625 cbcr_offset_32 = cbcr_offset_32 >> 5; 626 /* 627 * DM365: start address is 27-bit long address b26 - b23 are 628 * in offset register b12 - b9, and * bit 26 has to be '1' 629 */ 630 if (win->lconfig.pixfmt == PIXFMT_NV12) { 631 switch (layer) { 632 case WIN_VID0: 633 case WIN_VID1: 634 /* Y is in VID0 */ 635 osd_modify(sd, OSD_VIDWIN0OFST_V0AH, 636 ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> 637 (OSD_SRCADD_OFSET_SFT - 638 OSD_WINOFST_AH_SHIFT)) | 639 OSD_WINOFST_MASK, OSD_VIDWIN0OFST); 640 osd_modify(sd, OSD_VIDWINADH_V0AH, 641 (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> 642 (OSD_SRCADD_ADD_SFT - 643 OSD_VIDWINADH_V0AH_SHIFT), 644 OSD_VIDWINADH); 645 osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, 646 OSD_VIDWIN0ADL); 647 /* CbCr is in VID1 */ 648 osd_modify(sd, OSD_VIDWIN1OFST_V1AH, 649 ((cbcr_offset_32 & 650 OSD_SRC_ADDR_HIGH4) >> 651 (OSD_SRCADD_OFSET_SFT - 652 OSD_WINOFST_AH_SHIFT)) | 653 OSD_WINOFST_MASK, OSD_VIDWIN1OFST); 654 osd_modify(sd, OSD_VIDWINADH_V1AH, 655 (cbcr_offset_32 & 656 OSD_SRC_ADDR_HIGH7) >> 657 (OSD_SRCADD_ADD_SFT - 658 OSD_VIDWINADH_V1AH_SHIFT), 659 OSD_VIDWINADH); 660 osd_write(sd, cbcr_offset_32 & OSD_WINADL_MASK, 661 OSD_VIDWIN1ADL); 662 break; 663 default: 664 break; 665 } 666 } 667 668 switch (layer) { 669 case WIN_OSD0: 670 osd_modify(sd, OSD_OSDWIN0OFST_O0AH, 671 ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> 672 (OSD_SRCADD_OFSET_SFT - 673 OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK, 674 OSD_OSDWIN0OFST); 675 osd_modify(sd, OSD_OSDWINADH_O0AH, 676 (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> 677 (OSD_SRCADD_ADD_SFT - 678 OSD_OSDWINADH_O0AH_SHIFT), OSD_OSDWINADH); 679 osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, 680 OSD_OSDWIN0ADL); 681 break; 682 case WIN_VID0: 683 if (win->lconfig.pixfmt != PIXFMT_NV12) { 684 osd_modify(sd, OSD_VIDWIN0OFST_V0AH, 685 ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> 686 (OSD_SRCADD_OFSET_SFT - 687 OSD_WINOFST_AH_SHIFT)) | 688 OSD_WINOFST_MASK, OSD_VIDWIN0OFST); 689 osd_modify(sd, OSD_VIDWINADH_V0AH, 690 (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> 691 (OSD_SRCADD_ADD_SFT - 692 OSD_VIDWINADH_V0AH_SHIFT), 693 OSD_VIDWINADH); 694 osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, 695 OSD_VIDWIN0ADL); 696 } 697 break; 698 case WIN_OSD1: 699 osd_modify(sd, OSD_OSDWIN1OFST_O1AH, 700 ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> 701 (OSD_SRCADD_OFSET_SFT - 702 OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK, 703 OSD_OSDWIN1OFST); 704 osd_modify(sd, OSD_OSDWINADH_O1AH, 705 (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> 706 (OSD_SRCADD_ADD_SFT - 707 OSD_OSDWINADH_O1AH_SHIFT), 708 OSD_OSDWINADH); 709 osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, 710 OSD_OSDWIN1ADL); 711 break; 712 case WIN_VID1: 713 if (win->lconfig.pixfmt != PIXFMT_NV12) { 714 osd_modify(sd, OSD_VIDWIN1OFST_V1AH, 715 ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> 716 (OSD_SRCADD_OFSET_SFT - 717 OSD_WINOFST_AH_SHIFT)) | 718 OSD_WINOFST_MASK, OSD_VIDWIN1OFST); 719 osd_modify(sd, OSD_VIDWINADH_V1AH, 720 (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> 721 (OSD_SRCADD_ADD_SFT - 722 OSD_VIDWINADH_V1AH_SHIFT), 723 OSD_VIDWINADH); 724 osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, 725 OSD_VIDWIN1ADL); 726 } 727 break; 728 } 729 } 730} 731 732static void osd_start_layer(struct osd_state *sd, enum osd_layer layer, 733 unsigned long fb_base_phys, 734 unsigned long cbcr_ofst) 735{ 736 struct osd_state *osd = sd; 737 struct osd_window_state *win = &osd->win[layer]; 738 struct osd_layer_config *cfg = &win->lconfig; 739 unsigned long flags; 740 741 spin_lock_irqsave(&osd->lock, flags); 742 743 win->fb_base_phys = fb_base_phys & ~0x1F; 744 _osd_start_layer(sd, layer, fb_base_phys, cbcr_ofst); 745 746 if (layer == WIN_VID0) { 747 osd->pingpong = 748 _osd_dm6446_vid0_pingpong(sd, osd->field_inversion, 749 win->fb_base_phys, 750 cfg); 751 } 752 753 spin_unlock_irqrestore(&osd->lock, flags); 754} 755 756static void osd_get_layer_config(struct osd_state *sd, enum osd_layer layer, 757 struct osd_layer_config *lconfig) 758{ 759 struct osd_state *osd = sd; 760 struct osd_window_state *win = &osd->win[layer]; 761 unsigned long flags; 762 763 spin_lock_irqsave(&osd->lock, flags); 764 765 *lconfig = win->lconfig; 766 767 spin_unlock_irqrestore(&osd->lock, flags); 768} 769 770/** 771 * try_layer_config() - Try a specific configuration for the layer 772 * @sd - ptr to struct osd_state 773 * @layer - layer to configure 774 * @lconfig - layer configuration to try 775 * 776 * If the requested lconfig is completely rejected and the value of lconfig on 777 * exit is the current lconfig, then try_layer_config() returns 1. Otherwise, 778 * try_layer_config() returns 0. A return value of 0 does not necessarily mean 779 * that the value of lconfig on exit is identical to the value of lconfig on 780 * entry, but merely that it represents a change from the current lconfig. 781 */ 782static int try_layer_config(struct osd_state *sd, enum osd_layer layer, 783 struct osd_layer_config *lconfig) 784{ 785 struct osd_state *osd = sd; 786 struct osd_window_state *win = &osd->win[layer]; 787 int bad_config = 0; 788 789 /* verify that the pixel format is compatible with the layer */ 790 switch (lconfig->pixfmt) { 791 case PIXFMT_1BPP: 792 case PIXFMT_2BPP: 793 case PIXFMT_4BPP: 794 case PIXFMT_8BPP: 795 case PIXFMT_RGB565: 796 if (osd->vpbe_type == VPBE_VERSION_1) 797 bad_config = !is_vid_win(layer); 798 break; 799 case PIXFMT_YCbCrI: 800 case PIXFMT_YCrCbI: 801 bad_config = !is_vid_win(layer); 802 break; 803 case PIXFMT_RGB888: 804 if (osd->vpbe_type == VPBE_VERSION_1) 805 bad_config = !is_vid_win(layer); 806 else if ((osd->vpbe_type == VPBE_VERSION_3) || 807 (osd->vpbe_type == VPBE_VERSION_2)) 808 bad_config = !is_osd_win(layer); 809 break; 810 case PIXFMT_NV12: 811 if (osd->vpbe_type != VPBE_VERSION_2) 812 bad_config = 1; 813 else 814 bad_config = is_osd_win(layer); 815 break; 816 case PIXFMT_OSD_ATTR: 817 bad_config = (layer != WIN_OSD1); 818 break; 819 default: 820 bad_config = 1; 821 break; 822 } 823 if (bad_config) { 824 /* 825 * The requested pixel format is incompatible with the layer, 826 * so keep the current layer configuration. 827 */ 828 *lconfig = win->lconfig; 829 return bad_config; 830 } 831 832 /* DM6446: */ 833 /* only one OSD window at a time can use RGB pixel formats */ 834 if ((osd->vpbe_type == VPBE_VERSION_1) && 835 is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) { 836 enum osd_pix_format pixfmt; 837 if (layer == WIN_OSD0) 838 pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt; 839 else 840 pixfmt = osd->win[WIN_OSD0].lconfig.pixfmt; 841 842 if (is_rgb_pixfmt(pixfmt)) { 843 /* 844 * The other OSD window is already configured for an 845 * RGB, so keep the current layer configuration. 846 */ 847 *lconfig = win->lconfig; 848 return 1; 849 } 850 } 851 852 /* DM6446: only one video window at a time can use RGB888 */ 853 if ((osd->vpbe_type == VPBE_VERSION_1) && is_vid_win(layer) && 854 lconfig->pixfmt == PIXFMT_RGB888) { 855 enum osd_pix_format pixfmt; 856 857 if (layer == WIN_VID0) 858 pixfmt = osd->win[WIN_VID1].lconfig.pixfmt; 859 else 860 pixfmt = osd->win[WIN_VID0].lconfig.pixfmt; 861 862 if (pixfmt == PIXFMT_RGB888) { 863 /* 864 * The other video window is already configured for 865 * RGB888, so keep the current layer configuration. 866 */ 867 *lconfig = win->lconfig; 868 return 1; 869 } 870 } 871 872 /* window dimensions must be non-zero */ 873 if (!lconfig->line_length || !lconfig->xsize || !lconfig->ysize) { 874 *lconfig = win->lconfig; 875 return 1; 876 } 877 878 /* round line_length up to a multiple of 32 */ 879 lconfig->line_length = ((lconfig->line_length + 31) / 32) * 32; 880 lconfig->line_length = 881 min(lconfig->line_length, (unsigned)MAX_LINE_LENGTH); 882 lconfig->xsize = min(lconfig->xsize, (unsigned)MAX_WIN_SIZE); 883 lconfig->ysize = min(lconfig->ysize, (unsigned)MAX_WIN_SIZE); 884 lconfig->xpos = min(lconfig->xpos, (unsigned)MAX_WIN_SIZE); 885 lconfig->ypos = min(lconfig->ypos, (unsigned)MAX_WIN_SIZE); 886 lconfig->interlaced = (lconfig->interlaced != 0); 887 if (lconfig->interlaced) { 888 /* ysize and ypos must be even for interlaced displays */ 889 lconfig->ysize &= ~1; 890 lconfig->ypos &= ~1; 891 } 892 893 return 0; 894} 895 896static void _osd_disable_vid_rgb888(struct osd_state *sd) 897{ 898 /* 899 * The DM6446 supports RGB888 pixel format in a single video window. 900 * This routine disables RGB888 pixel format for both video windows. 901 * The caller must ensure that neither video window is currently 902 * configured for RGB888 pixel format. 903 */ 904 if (sd->vpbe_type == VPBE_VERSION_1) 905 osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL); 906} 907 908static void _osd_enable_vid_rgb888(struct osd_state *sd, 909 enum osd_layer layer) 910{ 911 /* 912 * The DM6446 supports RGB888 pixel format in a single video window. 913 * This routine enables RGB888 pixel format for the specified video 914 * window. The caller must ensure that the other video window is not 915 * currently configured for RGB888 pixel format, as this routine will 916 * disable RGB888 pixel format for the other window. 917 */ 918 if (sd->vpbe_type == VPBE_VERSION_1) { 919 if (layer == WIN_VID0) 920 osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, 921 OSD_MISCCTL_RGBEN, OSD_MISCCTL); 922 else if (layer == WIN_VID1) 923 osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, 924 OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, 925 OSD_MISCCTL); 926 } 927} 928 929static void _osd_set_cbcr_order(struct osd_state *sd, 930 enum osd_pix_format pixfmt) 931{ 932 /* 933 * The caller must ensure that all windows using YC pixfmt use the same 934 * Cb/Cr order. 935 */ 936 if (pixfmt == PIXFMT_YCbCrI) 937 osd_clear(sd, OSD_MODE_CS, OSD_MODE); 938 else if (pixfmt == PIXFMT_YCrCbI) 939 osd_set(sd, OSD_MODE_CS, OSD_MODE); 940} 941 942static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, 943 const struct osd_layer_config *lconfig) 944{ 945 u32 winmd = 0, winmd_mask = 0, bmw = 0; 946 947 _osd_set_cbcr_order(sd, lconfig->pixfmt); 948 949 switch (layer) { 950 case WIN_OSD0: 951 if (sd->vpbe_type == VPBE_VERSION_1) { 952 winmd_mask |= OSD_OSDWIN0MD_RGB0E; 953 if (lconfig->pixfmt == PIXFMT_RGB565) 954 winmd |= OSD_OSDWIN0MD_RGB0E; 955 } else if ((sd->vpbe_type == VPBE_VERSION_3) || 956 (sd->vpbe_type == VPBE_VERSION_2)) { 957 winmd_mask |= OSD_OSDWIN0MD_BMP0MD; 958 switch (lconfig->pixfmt) { 959 case PIXFMT_RGB565: 960 winmd |= (1 << 961 OSD_OSDWIN0MD_BMP0MD_SHIFT); 962 break; 963 case PIXFMT_RGB888: 964 winmd |= (2 << OSD_OSDWIN0MD_BMP0MD_SHIFT); 965 _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD0); 966 break; 967 case PIXFMT_YCbCrI: 968 case PIXFMT_YCrCbI: 969 winmd |= (3 << OSD_OSDWIN0MD_BMP0MD_SHIFT); 970 break; 971 default: 972 break; 973 } 974 } 975 976 winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0; 977 978 switch (lconfig->pixfmt) { 979 case PIXFMT_1BPP: 980 bmw = 0; 981 break; 982 case PIXFMT_2BPP: 983 bmw = 1; 984 break; 985 case PIXFMT_4BPP: 986 bmw = 2; 987 break; 988 case PIXFMT_8BPP: 989 bmw = 3; 990 break; 991 default: 992 break; 993 } 994 winmd |= (bmw << OSD_OSDWIN0MD_BMW0_SHIFT); 995 996 if (lconfig->interlaced) 997 winmd |= OSD_OSDWIN0MD_OFF0; 998 999 osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN0MD); 1000 osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN0OFST); 1001 osd_write(sd, lconfig->xpos, OSD_OSDWIN0XP); 1002 osd_write(sd, lconfig->xsize, OSD_OSDWIN0XL); 1003 if (lconfig->interlaced) { 1004 osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN0YP); 1005 osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN0YL); 1006 } else { 1007 osd_write(sd, lconfig->ypos, OSD_OSDWIN0YP); 1008 osd_write(sd, lconfig->ysize, OSD_OSDWIN0YL); 1009 } 1010 break; 1011 case WIN_VID0: 1012 winmd_mask |= OSD_VIDWINMD_VFF0; 1013 if (lconfig->interlaced) 1014 winmd |= OSD_VIDWINMD_VFF0; 1015 1016 osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD); 1017 osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN0OFST); 1018 osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP); 1019 osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL); 1020 /* 1021 * For YUV420P format the register contents are 1022 * duplicated in both VID registers 1023 */ 1024 if ((sd->vpbe_type == VPBE_VERSION_2) && 1025 (lconfig->pixfmt == PIXFMT_NV12)) { 1026 /* other window also */ 1027 if (lconfig->interlaced) { 1028 winmd_mask |= OSD_VIDWINMD_VFF1; 1029 winmd |= OSD_VIDWINMD_VFF1; 1030 osd_modify(sd, winmd_mask, winmd, 1031 OSD_VIDWINMD); 1032 } 1033 1034 osd_modify(sd, OSD_MISCCTL_S420D, 1035 OSD_MISCCTL_S420D, OSD_MISCCTL); 1036 osd_write(sd, lconfig->line_length >> 5, 1037 OSD_VIDWIN1OFST); 1038 osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP); 1039 osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL); 1040 /* 1041 * if NV21 pixfmt and line length not 32B 1042 * aligned (e.g. NTSC), Need to set window 1043 * X pixel size to be 32B aligned as well 1044 */ 1045 if (lconfig->xsize % 32) { 1046 osd_write(sd, 1047 ((lconfig->xsize + 31) & ~31), 1048 OSD_VIDWIN1XL); 1049 osd_write(sd, 1050 ((lconfig->xsize + 31) & ~31), 1051 OSD_VIDWIN0XL); 1052 } 1053 } else if ((sd->vpbe_type == VPBE_VERSION_2) && 1054 (lconfig->pixfmt != PIXFMT_NV12)) { 1055 osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D, 1056 OSD_MISCCTL); 1057 } 1058 1059 if (lconfig->interlaced) { 1060 osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP); 1061 osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL); 1062 if ((sd->vpbe_type == VPBE_VERSION_2) && 1063 lconfig->pixfmt == PIXFMT_NV12) { 1064 osd_write(sd, lconfig->ypos >> 1, 1065 OSD_VIDWIN1YP); 1066 osd_write(sd, lconfig->ysize >> 1, 1067 OSD_VIDWIN1YL); 1068 } 1069 } else { 1070 osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP); 1071 osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL); 1072 if ((sd->vpbe_type == VPBE_VERSION_2) && 1073 lconfig->pixfmt == PIXFMT_NV12) { 1074 osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP); 1075 osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL); 1076 } 1077 } 1078 break; 1079 case WIN_OSD1: 1080 /* 1081 * The caller must ensure that OSD1 is disabled prior to 1082 * switching from a normal mode to attribute mode or from 1083 * attribute mode to a normal mode. 1084 */ 1085 if (lconfig->pixfmt == PIXFMT_OSD_ATTR) { 1086 if (sd->vpbe_type == VPBE_VERSION_1) { 1087 winmd_mask |= OSD_OSDWIN1MD_ATN1E | 1088 OSD_OSDWIN1MD_RGB1E | OSD_OSDWIN1MD_CLUTS1 | 1089 OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1; 1090 } else { 1091 winmd_mask |= OSD_OSDWIN1MD_BMP1MD | 1092 OSD_OSDWIN1MD_CLUTS1 | OSD_OSDWIN1MD_BLND1 | 1093 OSD_OSDWIN1MD_TE1; 1094 } 1095 } else { 1096 if (sd->vpbe_type == VPBE_VERSION_1) { 1097 winmd_mask |= OSD_OSDWIN1MD_RGB1E; 1098 if (lconfig->pixfmt == PIXFMT_RGB565) 1099 winmd |= OSD_OSDWIN1MD_RGB1E; 1100 } else if ((sd->vpbe_type == VPBE_VERSION_3) 1101 || (sd->vpbe_type == VPBE_VERSION_2)) { 1102 winmd_mask |= OSD_OSDWIN1MD_BMP1MD; 1103 switch (lconfig->pixfmt) { 1104 case PIXFMT_RGB565: 1105 winmd |= 1106 (1 << OSD_OSDWIN1MD_BMP1MD_SHIFT); 1107 break; 1108 case PIXFMT_RGB888: 1109 winmd |= 1110 (2 << OSD_OSDWIN1MD_BMP1MD_SHIFT); 1111 _osd_enable_rgb888_pixblend(sd, 1112 OSDWIN_OSD1); 1113 break; 1114 case PIXFMT_YCbCrI: 1115 case PIXFMT_YCrCbI: 1116 winmd |= 1117 (3 << OSD_OSDWIN1MD_BMP1MD_SHIFT); 1118 break; 1119 default: 1120 break; 1121 } 1122 } 1123 1124 winmd_mask |= OSD_OSDWIN1MD_BMW1; 1125 switch (lconfig->pixfmt) { 1126 case PIXFMT_1BPP: 1127 bmw = 0; 1128 break; 1129 case PIXFMT_2BPP: 1130 bmw = 1; 1131 break; 1132 case PIXFMT_4BPP: 1133 bmw = 2; 1134 break; 1135 case PIXFMT_8BPP: 1136 bmw = 3; 1137 break; 1138 default: 1139 break; 1140 } 1141 winmd |= (bmw << OSD_OSDWIN1MD_BMW1_SHIFT); 1142 } 1143 1144 winmd_mask |= OSD_OSDWIN1MD_OFF1; 1145 if (lconfig->interlaced) 1146 winmd |= OSD_OSDWIN1MD_OFF1; 1147 1148 osd_modify(sd, winmd_mask, winmd, OSD_OSDWIN1MD); 1149 osd_write(sd, lconfig->line_length >> 5, OSD_OSDWIN1OFST); 1150 osd_write(sd, lconfig->xpos, OSD_OSDWIN1XP); 1151 osd_write(sd, lconfig->xsize, OSD_OSDWIN1XL); 1152 if (lconfig->interlaced) { 1153 osd_write(sd, lconfig->ypos >> 1, OSD_OSDWIN1YP); 1154 osd_write(sd, lconfig->ysize >> 1, OSD_OSDWIN1YL); 1155 } else { 1156 osd_write(sd, lconfig->ypos, OSD_OSDWIN1YP); 1157 osd_write(sd, lconfig->ysize, OSD_OSDWIN1YL); 1158 } 1159 break; 1160 case WIN_VID1: 1161 winmd_mask |= OSD_VIDWINMD_VFF1; 1162 if (lconfig->interlaced) 1163 winmd |= OSD_VIDWINMD_VFF1; 1164 1165 osd_modify(sd, winmd_mask, winmd, OSD_VIDWINMD); 1166 osd_write(sd, lconfig->line_length >> 5, OSD_VIDWIN1OFST); 1167 osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP); 1168 osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL); 1169 /* 1170 * For YUV420P format the register contents are 1171 * duplicated in both VID registers 1172 */ 1173 if (sd->vpbe_type == VPBE_VERSION_2) { 1174 if (lconfig->pixfmt == PIXFMT_NV12) { 1175 /* other window also */ 1176 if (lconfig->interlaced) { 1177 winmd_mask |= OSD_VIDWINMD_VFF0; 1178 winmd |= OSD_VIDWINMD_VFF0; 1179 osd_modify(sd, winmd_mask, winmd, 1180 OSD_VIDWINMD); 1181 } 1182 osd_modify(sd, OSD_MISCCTL_S420D, 1183 OSD_MISCCTL_S420D, OSD_MISCCTL); 1184 osd_write(sd, lconfig->line_length >> 5, 1185 OSD_VIDWIN0OFST); 1186 osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP); 1187 osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL); 1188 } else { 1189 osd_modify(sd, OSD_MISCCTL_S420D, 1190 ~OSD_MISCCTL_S420D, OSD_MISCCTL); 1191 } 1192 } 1193 1194 if (lconfig->interlaced) { 1195 osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP); 1196 osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL); 1197 if ((sd->vpbe_type == VPBE_VERSION_2) && 1198 lconfig->pixfmt == PIXFMT_NV12) { 1199 osd_write(sd, lconfig->ypos >> 1, 1200 OSD_VIDWIN0YP); 1201 osd_write(sd, lconfig->ysize >> 1, 1202 OSD_VIDWIN0YL); 1203 } 1204 } else { 1205 osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP); 1206 osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL); 1207 if ((sd->vpbe_type == VPBE_VERSION_2) && 1208 lconfig->pixfmt == PIXFMT_NV12) { 1209 osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP); 1210 osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL); 1211 } 1212 } 1213 break; 1214 } 1215} 1216 1217static int osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, 1218 struct osd_layer_config *lconfig) 1219{ 1220 struct osd_state *osd = sd; 1221 struct osd_window_state *win = &osd->win[layer]; 1222 struct osd_layer_config *cfg = &win->lconfig; 1223 unsigned long flags; 1224 int reject_config; 1225 1226 spin_lock_irqsave(&osd->lock, flags); 1227 1228 reject_config = try_layer_config(sd, layer, lconfig); 1229 if (reject_config) { 1230 spin_unlock_irqrestore(&osd->lock, flags); 1231 return reject_config; 1232 } 1233 1234 /* update the current Cb/Cr order */ 1235 if (is_yc_pixfmt(lconfig->pixfmt)) 1236 osd->yc_pixfmt = lconfig->pixfmt; 1237 1238 /* 1239 * If we are switching OSD1 from normal mode to attribute mode or from 1240 * attribute mode to normal mode, then we must disable the window. 1241 */ 1242 if (layer == WIN_OSD1) { 1243 if (((lconfig->pixfmt == PIXFMT_OSD_ATTR) && 1244 (cfg->pixfmt != PIXFMT_OSD_ATTR)) || 1245 ((lconfig->pixfmt != PIXFMT_OSD_ATTR) && 1246 (cfg->pixfmt == PIXFMT_OSD_ATTR))) { 1247 win->is_enabled = 0; 1248 _osd_disable_layer(sd, layer); 1249 } 1250 } 1251 1252 _osd_set_layer_config(sd, layer, lconfig); 1253 1254 if (layer == WIN_OSD1) { 1255 struct osd_osdwin_state *osdwin_state = 1256 &osd->osdwin[OSDWIN_OSD1]; 1257 1258 if ((lconfig->pixfmt != PIXFMT_OSD_ATTR) && 1259 (cfg->pixfmt == PIXFMT_OSD_ATTR)) { 1260 /* 1261 * We just switched OSD1 from attribute mode to normal 1262 * mode, so we must initialize the CLUT select, the 1263 * blend factor, transparency colorkey enable, and 1264 * attenuation enable (DM6446 only) bits in the 1265 * OSDWIN1MD register. 1266 */ 1267 _osd_set_osd_clut(sd, OSDWIN_OSD1, 1268 osdwin_state->clut); 1269 _osd_set_blending_factor(sd, OSDWIN_OSD1, 1270 osdwin_state->blend); 1271 if (osdwin_state->colorkey_blending) { 1272 _osd_enable_color_key(sd, OSDWIN_OSD1, 1273 osdwin_state-> 1274 colorkey, 1275 lconfig->pixfmt); 1276 } else 1277 _osd_disable_color_key(sd, OSDWIN_OSD1); 1278 _osd_set_rec601_attenuation(sd, OSDWIN_OSD1, 1279 osdwin_state-> 1280 rec601_attenuation); 1281 } else if ((lconfig->pixfmt == PIXFMT_OSD_ATTR) && 1282 (cfg->pixfmt != PIXFMT_OSD_ATTR)) { 1283 /* 1284 * We just switched OSD1 from normal mode to attribute 1285 * mode, so we must initialize the blink enable and 1286 * blink interval bits in the OSDATRMD register. 1287 */ 1288 _osd_set_blink_attribute(sd, osd->is_blinking, 1289 osd->blink); 1290 } 1291 } 1292 1293 /* 1294 * If we just switched to a 1-, 2-, or 4-bits-per-pixel bitmap format 1295 * then configure a default palette map. 1296 */ 1297 if ((lconfig->pixfmt != cfg->pixfmt) && 1298 ((lconfig->pixfmt == PIXFMT_1BPP) || 1299 (lconfig->pixfmt == PIXFMT_2BPP) || 1300 (lconfig->pixfmt == PIXFMT_4BPP))) { 1301 enum osd_win_layer osdwin = 1302 ((layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1); 1303 struct osd_osdwin_state *osdwin_state = 1304 &osd->osdwin[osdwin]; 1305 unsigned char clut_index; 1306 unsigned char clut_entries = 0; 1307 1308 switch (lconfig->pixfmt) { 1309 case PIXFMT_1BPP: 1310 clut_entries = 2; 1311 break; 1312 case PIXFMT_2BPP: 1313 clut_entries = 4; 1314 break; 1315 case PIXFMT_4BPP: 1316 clut_entries = 16; 1317 break; 1318 default: 1319 break; 1320 } 1321 /* 1322 * The default palette map maps the pixel value to the clut 1323 * index, i.e. pixel value 0 maps to clut entry 0, pixel value 1324 * 1 maps to clut entry 1, etc. 1325 */ 1326 for (clut_index = 0; clut_index < 16; clut_index++) { 1327 osdwin_state->palette_map[clut_index] = clut_index; 1328 if (clut_index < clut_entries) { 1329 _osd_set_palette_map(sd, osdwin, clut_index, 1330 clut_index, 1331 lconfig->pixfmt); 1332 } 1333 } 1334 } 1335 1336 *cfg = *lconfig; 1337 /* DM6446: configure the RGB888 enable and window selection */ 1338 if (osd->win[WIN_VID0].lconfig.pixfmt == PIXFMT_RGB888) 1339 _osd_enable_vid_rgb888(sd, WIN_VID0); 1340 else if (osd->win[WIN_VID1].lconfig.pixfmt == PIXFMT_RGB888) 1341 _osd_enable_vid_rgb888(sd, WIN_VID1); 1342 else 1343 _osd_disable_vid_rgb888(sd); 1344 1345 if (layer == WIN_VID0) { 1346 osd->pingpong = 1347 _osd_dm6446_vid0_pingpong(sd, osd->field_inversion, 1348 win->fb_base_phys, 1349 cfg); 1350 } 1351 1352 spin_unlock_irqrestore(&osd->lock, flags); 1353 1354 return 0; 1355} 1356 1357static void osd_init_layer(struct osd_state *sd, enum osd_layer layer) 1358{ 1359 struct osd_state *osd = sd; 1360 struct osd_window_state *win = &osd->win[layer]; 1361 enum osd_win_layer osdwin; 1362 struct osd_osdwin_state *osdwin_state; 1363 struct osd_layer_config *cfg = &win->lconfig; 1364 unsigned long flags; 1365 1366 spin_lock_irqsave(&osd->lock, flags); 1367 1368 win->is_enabled = 0; 1369 _osd_disable_layer(sd, layer); 1370 1371 win->h_zoom = ZOOM_X1; 1372 win->v_zoom = ZOOM_X1; 1373 _osd_set_zoom(sd, layer, win->h_zoom, win->v_zoom); 1374 1375 win->fb_base_phys = 0; 1376 _osd_start_layer(sd, layer, win->fb_base_phys, 0); 1377 1378 cfg->line_length = 0; 1379 cfg->xsize = 0; 1380 cfg->ysize = 0; 1381 cfg->xpos = 0; 1382 cfg->ypos = 0; 1383 cfg->interlaced = 0; 1384 switch (layer) { 1385 case WIN_OSD0: 1386 case WIN_OSD1: 1387 osdwin = (layer == WIN_OSD0) ? OSDWIN_OSD0 : OSDWIN_OSD1; 1388 osdwin_state = &osd->osdwin[osdwin]; 1389 /* 1390 * Other code relies on the fact that OSD windows default to a 1391 * bitmap pixel format when they are deallocated, so don't 1392 * change this default pixel format. 1393 */ 1394 cfg->pixfmt = PIXFMT_8BPP; 1395 _osd_set_layer_config(sd, layer, cfg); 1396 osdwin_state->clut = RAM_CLUT; 1397 _osd_set_osd_clut(sd, osdwin, osdwin_state->clut); 1398 osdwin_state->colorkey_blending = 0; 1399 _osd_disable_color_key(sd, osdwin); 1400 osdwin_state->blend = OSD_8_VID_0; 1401 _osd_set_blending_factor(sd, osdwin, osdwin_state->blend); 1402 osdwin_state->rec601_attenuation = 0; 1403 _osd_set_rec601_attenuation(sd, osdwin, 1404 osdwin_state-> 1405 rec601_attenuation); 1406 if (osdwin == OSDWIN_OSD1) { 1407 osd->is_blinking = 0; 1408 osd->blink = BLINK_X1; 1409 } 1410 break; 1411 case WIN_VID0: 1412 case WIN_VID1: 1413 cfg->pixfmt = osd->yc_pixfmt; 1414 _osd_set_layer_config(sd, layer, cfg); 1415 break; 1416 } 1417 1418 spin_unlock_irqrestore(&osd->lock, flags); 1419} 1420 1421static void osd_release_layer(struct osd_state *sd, enum osd_layer layer) 1422{ 1423 struct osd_state *osd = sd; 1424 struct osd_window_state *win = &osd->win[layer]; 1425 unsigned long flags; 1426 1427 spin_lock_irqsave(&osd->lock, flags); 1428 1429 if (!win->is_allocated) { 1430 spin_unlock_irqrestore(&osd->lock, flags); 1431 return; 1432 } 1433 1434 spin_unlock_irqrestore(&osd->lock, flags); 1435 osd_init_layer(sd, layer); 1436 spin_lock_irqsave(&osd->lock, flags); 1437 1438 win->is_allocated = 0; 1439 1440 spin_unlock_irqrestore(&osd->lock, flags); 1441} 1442 1443static int osd_request_layer(struct osd_state *sd, enum osd_layer layer) 1444{ 1445 struct osd_state *osd = sd; 1446 struct osd_window_state *win = &osd->win[layer]; 1447 unsigned long flags; 1448 1449 spin_lock_irqsave(&osd->lock, flags); 1450 1451 if (win->is_allocated) { 1452 spin_unlock_irqrestore(&osd->lock, flags); 1453 return -1; 1454 } 1455 win->is_allocated = 1; 1456 1457 spin_unlock_irqrestore(&osd->lock, flags); 1458 1459 return 0; 1460} 1461 1462static void _osd_init(struct osd_state *sd) 1463{ 1464 osd_write(sd, 0, OSD_MODE); 1465 osd_write(sd, 0, OSD_VIDWINMD); 1466 osd_write(sd, 0, OSD_OSDWIN0MD); 1467 osd_write(sd, 0, OSD_OSDWIN1MD); 1468 osd_write(sd, 0, OSD_RECTCUR); 1469 osd_write(sd, 0, OSD_MISCCTL); 1470 if (sd->vpbe_type == VPBE_VERSION_3) { 1471 osd_write(sd, 0, OSD_VBNDRY); 1472 osd_write(sd, 0, OSD_EXTMODE); 1473 osd_write(sd, OSD_MISCCTL_DMANG, OSD_MISCCTL); 1474 } 1475} 1476 1477static void osd_set_left_margin(struct osd_state *sd, u32 val) 1478{ 1479 osd_write(sd, val, OSD_BASEPX); 1480} 1481 1482static void osd_set_top_margin(struct osd_state *sd, u32 val) 1483{ 1484 osd_write(sd, val, OSD_BASEPY); 1485} 1486 1487static int osd_initialize(struct osd_state *osd) 1488{ 1489 if (osd == NULL) 1490 return -ENODEV; 1491 _osd_init(osd); 1492 1493 /* set default Cb/Cr order */ 1494 osd->yc_pixfmt = PIXFMT_YCbCrI; 1495 1496 if (osd->vpbe_type == VPBE_VERSION_3) { 1497 /* 1498 * ROM CLUT1 on the DM355 is similar (identical?) to ROM CLUT0 1499 * on the DM6446, so make ROM_CLUT1 the default on the DM355. 1500 */ 1501 osd->rom_clut = ROM_CLUT1; 1502 } 1503 1504 _osd_set_field_inversion(osd, osd->field_inversion); 1505 _osd_set_rom_clut(osd, osd->rom_clut); 1506 1507 osd_init_layer(osd, WIN_OSD0); 1508 osd_init_layer(osd, WIN_VID0); 1509 osd_init_layer(osd, WIN_OSD1); 1510 osd_init_layer(osd, WIN_VID1); 1511 1512 return 0; 1513} 1514 1515static const struct vpbe_osd_ops osd_ops = { 1516 .initialize = osd_initialize, 1517 .request_layer = osd_request_layer, 1518 .release_layer = osd_release_layer, 1519 .enable_layer = osd_enable_layer, 1520 .disable_layer = osd_disable_layer, 1521 .set_layer_config = osd_set_layer_config, 1522 .get_layer_config = osd_get_layer_config, 1523 .start_layer = osd_start_layer, 1524 .set_left_margin = osd_set_left_margin, 1525 .set_top_margin = osd_set_top_margin, 1526}; 1527 1528static int osd_probe(struct platform_device *pdev) 1529{ 1530 struct osd_platform_data *pdata; 1531 struct osd_state *osd; 1532 struct resource *res; 1533 int ret = 0; 1534 1535 osd = kzalloc(sizeof(struct osd_state), GFP_KERNEL); 1536 if (osd == NULL) 1537 return -ENOMEM; 1538 1539 osd->dev = &pdev->dev; 1540 pdata = (struct osd_platform_data *)pdev->dev.platform_data; 1541 osd->vpbe_type = (enum vpbe_version)pdata->vpbe_type; 1542 if (NULL == pdev->dev.platform_data) { 1543 dev_err(osd->dev, "No platform data defined for OSD" 1544 " sub device\n"); 1545 ret = -ENOENT; 1546 goto free_mem; 1547 } 1548 1549 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1550 if (!res) { 1551 dev_err(osd->dev, "Unable to get OSD register address map\n"); 1552 ret = -ENODEV; 1553 goto free_mem; 1554 } 1555 osd->osd_base_phys = res->start; 1556 osd->osd_size = resource_size(res); 1557 if (!request_mem_region(osd->osd_base_phys, osd->osd_size, 1558 MODULE_NAME)) { 1559 dev_err(osd->dev, "Unable to reserve OSD MMIO region\n"); 1560 ret = -ENODEV; 1561 goto free_mem; 1562 } 1563 osd->osd_base = (unsigned long)ioremap_nocache(res->start, 1564 osd->osd_size); 1565 if (!osd->osd_base) { 1566 dev_err(osd->dev, "Unable to map the OSD region\n"); 1567 ret = -ENODEV; 1568 goto release_mem_region; 1569 } 1570 spin_lock_init(&osd->lock); 1571 osd->ops = osd_ops; 1572 platform_set_drvdata(pdev, osd); 1573 dev_notice(osd->dev, "OSD sub device probe success\n"); 1574 return ret; 1575 1576release_mem_region: 1577 release_mem_region(osd->osd_base_phys, osd->osd_size); 1578free_mem: 1579 kfree(osd); 1580 return ret; 1581} 1582 1583static int osd_remove(struct platform_device *pdev) 1584{ 1585 struct osd_state *osd = platform_get_drvdata(pdev); 1586 1587 iounmap((void *)osd->osd_base); 1588 release_mem_region(osd->osd_base_phys, osd->osd_size); 1589 kfree(osd); 1590 return 0; 1591} 1592 1593static struct platform_driver osd_driver = { 1594 .probe = osd_probe, 1595 .remove = osd_remove, 1596 .driver = { 1597 .name = MODULE_NAME, 1598 .owner = THIS_MODULE, 1599 }, 1600}; 1601 1602module_platform_driver(osd_driver); 1603 1604MODULE_LICENSE("GPL"); 1605MODULE_DESCRIPTION("DaVinci OSD Manager Driver"); 1606MODULE_AUTHOR("Texas Instruments"); 1607