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