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